Какой уровень изоляции следует использовать для бронирования рейса - PullRequest
4 голосов
/ 16 марта 2012

У меня есть программа бронирования авиабилетов, используйте 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' 

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

Q1: Должен ли я использовать замки или уровни изоляции? Есть ли какая-то польза для его использования?

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

Ответы [ 3 ]

4 голосов
/ 07 апреля 2012

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

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

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

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

2 голосов
/ 16 марта 2012

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

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

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

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

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

Update inventory
set Sold = Sold + @seats
where FlightNumber = 'F3241b'
AND Total - Sold >= @seats
0 голосов
/ 04 августа 2012

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

Они говорят о приложении по прокату автомобилей.

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

...