Это трудно сделать в Oracle 10g.В 11g синтаксис SELECT FOR UPDATE ... SKIP LOCKED
делает это простым.
Простой оператор UPDATE
будет сериализован.Как будет SELECT FOR UPDATE
.Конечно, два конкурирующих процесса никогда не получат одинаковые строки;проблема в том, что в лучшем случае они будут сериализованы, а в худшем - заблокированы.
Рекомендуется использовать Oracle Advanced Queuing (или реализацию очередей по вашему выбору), чтобы поставить в очередь идентификаторы, которые будутобрабатываются и позволяют реализации очередей управлять конфликтом значений.
-
SQL будет работать, но не будет работать с ORA-00054, если второй пользователь запускает его для того жесмещений, пока кто-то заблокировал этот диапазон.Это может быть смягчено путем включения выбора в цикл, перехвата ошибки ORA-00054 и использования ее для увеличения смещений.
select * from my_table
where rowid in
(select row_id
from (select rowid as row_id, rownum as rn
from mytable where some_condition
order by deterministic_sort_order)
where rn between :low_rn and :hi_rn
)
for update nowait;
Выражение сортировки должно быть детерминированным (просто включите первичный ключ какконец выражения сортировки) для предотвращения столкновений.