Выбор Oracle для поведения обновления

Проблема, которую мы пытаемся решить, выглядит так.

  • У нас есть таблица, полная строк, которые представляют карты. Цель транзакции резервирования - назначить карту клиенту
  • Карта не может принадлежать многим клиентам
  • Через некоторое время (если она не куплена) карту необходимо вернуть в пул доступных ресурсов
  • Резервирование может выполняться многими клиентами одновременно
  • Мы используем базу данных Oracle для хранения данных, поэтому решение должно работать как минимум на Oracle 11

Наше решение - присвоить карте статус и сохранить дату резервирования. При бронировании карты мы делаем это с помощью инструкции «выбрать для обновления». Запрос ищет доступные карты и карты, которые были зарезервированы давным-давно.

Однако наш запрос работает не так, как ожидалось.

Я подготовил упрощенную ситуацию, чтобы объяснить проблему. У нас есть таблица card_numbers, полная данных - все строки имеют ненулевые идентификационные номера. Теперь давайте попробуем заблокировать некоторые из них.

-- first, in session 1
set autocommit off;

select id from card_numbers  
where id is not null  
and rownum <= 1  
for update skip locked;

Здесь мы не фиксируем транзакцию, строка должна быть заблокирована.

-- later, in session 2
set autocommit off;

select id from card_numbers  
where id is not null  
and rownum <= 1  
for update skip locked;

Ожидаемое поведение состоит в том, что в обоих сеансах мы получаем одну разную строку, удовлетворяющую условиям запроса.

Однако так не работает. В зависимости от того, используем ли мы часть запроса с пропуском блокировки или нет - поведение меняется:

  • без «пропустить заблокирован» - второй сеанс заблокирован - ожидание фиксации транзакции или откат в первом сеансе
  • с «пропустить» заблокирован "- второй запрос сразу возвращает пустой набор результатов

Итак, после этого длинного вступления возникает вопрос.

Возможно ли в Oracle желаемое поведение блокировки? Если да, то что мы делаем не так? Какое решение будет правильным?

18
задан mateusz.fiolka 30 January 2013 в 23:24
поделиться