Какой уровень изоляции следует использовать для бронирования рейса

У меня есть программа бронирования авиабилетов, использующая mssql. Для резервирования рейсов я хочу быть уверенным, следует ли мне использовать уровень изоляции или блокировки?

(это пример кода, моя проблема - уровень изоляции, в этой ситуации не выполняйте резервирование)

В моей базе данных есть таблица для инвентаризации, например:

Inventory Table
------------------------
id (Pk),
FlightNumber,
Total,
Sold

теперь, если кто-то хочет зарезервировать рейс, я использую этот код в транзакции

Decalre @total int;
Decalre @sold int;
Select @total=Total,@sold=Sold From Inventory where FlightNumber='F3241b';

IF @total-@sold > 0
BEGIN
   Update inventory set Sold=Sold+1 where FlightNumber='F3241b';
   PRINT 'Reserve Complete'
END
ELSE
PRINT 'this flight is full' 

у меня есть этот вопрос:

В1: Следует ли мне использовать уровни блокировки или изоляции? Есть ли какие-либо преимущества для производительности от их использования?

Q2: в соответствии с Q1, какой уровень изоляции или замок я должен использовать


person raoof hojat    schedule 16.03.2012    source источник


Ответы (3)


Если вы хотите увидеть, какой уровень изоляции заставит образец кода работать в его нынешнем виде, а не как лучше всего решить проблему, решаемую образцом кода, вам потребуются гарантии как минимум REPEATABLE READ.

Базы данных, которые используют строгую двухфазную блокировку (S2PL) для параллелизма, позволяют транзакциям READ COMMITTED сбрасывать общие блокировки по завершении каждого оператора или даже раньше, поэтому между моментом, когда транзакция A проверяет доступность, и моментом, когда она запрашивает места, кто-то другой может пройти с транзакцией B и прочитать снова, не вызывая сбоя ни одной из транзакций. Транзакция A может на короткое время заблокировать транзакцию B, но обе будут обновлены, и вы можете быть перепроданы.

В базах данных, использующих управление многоверсионным параллелизмом (MVCC) для параллелизма, чтение не блокирует запись, а запись не блокирует чтение. В READ COMMITTED каждый оператор использует новый моментальный снимок базы данных на основе того, что было зафиксировано, и по крайней мере в некоторых (я знаю, что это верно в PostgreSQL) одновременные записи разрешаются без ошибок. Таким образом, даже если транзакция A находилась в процессе обновления счетчика проданных товаров или была сделана, но не зафиксирована, транзакция B увидит старый счетчик и продолжит обновление. Когда он попытался обновить, он мог заблокировать ожидание предыдущего обновления, но после этого он найдет новую версию строки, проверит, соответствует ли она критериям выбора, обновит, если это так, и проигнорирует строку, если нет, и приступить к фиксации без ошибок. Итак, вы снова перепроданы.

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

person kgrittn    schedule 06.04.2012

Вы слишком усложняете ситуацию. Все ваши запросы можно заменить на:

Update inventory
set Sold = Sold + 1
where FlightNumber = 'F3241b'
AND Total - Sold > 0  -- Important!

Если полет заполнен, ОБНОВЛЕНИЕ не произойдет (второе условие не выполнено) и вернет 0 измененных строки. Если это так, значит, рейс заполнен. В противном случае запрос изменяет значение Sold и возвращает измененную строку 1.

В этом случае подойдет любой уровень изоляции, потому что отдельный запрос всегда атомарен. Это в чем-то похоже на optimistic-lock.

Кстати, этот запрос можно легко настроить, чтобы можно было атомарно выполнять произвольное количество резервирований:

Update inventory
set Sold = Sold + @seats
where FlightNumber = 'F3241b'
AND Total - Sold >= @seats
person Tomasz Nurkiewicz    schedule 16.03.2012
comment
TanQ, но на самом деле моя проблема - уровни изоляции, я придумал этот пример, чтобы узнать, хочу ли я сделать то же самое, что мне делать? Можете ли вы ответить исходным примером - person raoof hojat; 16.03.2012

См. Эту ссылку, которая объясняет уровень SNAPSHOT ISOLATION в SQL Server. http://msdn.microsoft.com/en-us/library/ms345124(v=sql.90).aspx

Они говорят о заявке на аренду автомобиля.

Если вам нужен более строгий уровень изоляции, вы можете перейти к IsolationLevel Serializable. Но имейте в виду, что это подвержено блокировкам и может повлиять на вашу производительность.

person eightyeight    schedule 04.08.2012