Если вам нужно убедиться, что одновременно может выполняться только одна транзакция, вы можете использовать синтаксис 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.