СЧИТАЙТЕ уровень изоляции базы данных COMMITTED в оракуле

Я предположил также, что компилятор не генерирует код относительно "a", поскольку на это не ссылаются, но тем не менее, это не правильное поведение, поскольку деструктор делает что-то, что должно быть выполнено.

Так, я попробовал в VS2008/vc9 (+SP1), Отладка и Выпуск, и ~A называют после того, как исключение выдается, выходя f () - который является правильным поведением, если я прав.

Теперь я просто попробовал VS2005/vc8 (+SP1), и это - то же поведение.

я использовал точки останова, чтобы быть уверенным. Я просто сверился с консолью, и у меня есть сообщение "~A" также. Возможно, Вы сделали это неправильно где-то в другом месте?

5
задан Ben 22 September 2009 в 23:47
поделиться

3 ответа

ваше решение должно работать: ваше первое обновление заблокирует всю таблицу. Если другая транзакция не будет завершена, обновление будет ждать. Ваше второе обновление гарантирует, что только одна строка будет иметь значение 1, потому что вы блокируете таблицу (однако это не препятствует операциям INSERT).

Вы также должны убедиться, что строка с RISK_MODEL_ID существует (или у вас будет нулевая строка со значением «1» в конце транзакции).

Чтобы предотвратить одновременное выполнение инструкций INSERT, вы должны ЗАБЛОКИРОВАТЬ таблицу (в ЭКСКЛЮЗИВНОМ РЕЖИМЕ).

3
ответ дан 14 December 2019 в 04:43
поделиться

Вы можете рассмотреть возможность использования уникального, основанного на функциях индекса, чтобы позволить Oracle обрабатывать ограничение наличия только одной строки с активированным флагом, установленным на 1.

CREATE UNIQUE INDEX MODEL_IX ON MODEL ( DECODE(ACTIVATED, 1, 1, NULL));

Это остановило бы наличие более чем одной строки флаг установлен в 1, но не означает, что всегда есть одна строка с установленным флагом 1.

3
ответ дан 14 December 2019 в 04:43
поделиться

Если вы хотите убедиться, что одновременно может выполняться только одна транзакция, вы можете использовать синтаксис FOR UPDATE . Поскольку у вас есть одна строка, которая требует блокировки, это очень эффективный подход.

declare
    cursor c is 
        select activated
        from model
        where activated = 1
        for update of activated;
    r c%rowtype;
begin
    open c;
    --  this statement will fail if another transaction is running
    fetch c in r;
    ....
    update model
    set activated = 0
    where current of c;

    update model
    set activated = 1
    where risk_model_id = ?;

    close c;

    commit;
end;
/

commit освобождает блокировку.

По умолчанию ожидается освобождение строки. В противном случае мы можем указать NOWAIT , и в этом случае любой другой сеанс, пытающийся обновить текущую активную строку, немедленно завершится ошибкой, или мы можем добавить параметр WAIT с временем опроса. NOWAIT - это вариант, который позволяет полностью избежать риска зависания, а также дает нам возможность сообщить пользователю, что кто-то другой обновляет таблицу, о чем он может захотеть узнать.

Этот подход гораздо более масштабируем, чем обновление всех строк в таблице. Используйте индекс на основе функций, как показал WW, чтобы обеспечить соблюдение правила, согласно которому только одна строка может иметь ACTIVATED = 1.

2
ответ дан 14 December 2019 в 04:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: