Какие намеки на блокировку следует использовать (T-SQL)?

Я хочу реализовать атомную транзакцию следующим образом:

BEGIN TRAN A

SELECT id
FROM Inventory
WITH (???)
WHERE material_id = 25 AND quantity > 10

/*
Process some things using the inventory record and
eventually write some updates that are dependent on the fact that
that specific inventory record had sufficient quantity (greater than 10).
*/

COMMIT TRAN A

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

Итак, вопрос в том, какие блокирующие подсказки следует использовать в предложении WITH, чтобы предотвратить изменение выбранной записи инвентаря до того, как я закончу свои обновления и сделаю транзакцию?

EDIT: Поэтому, благодаря Джону, хорошим решением является установка уровня изоляции транзакций на REPEATABLE READ. Это позволит убедиться, что "никакие другие транзакции не могут изменять данные, которые были прочитаны текущей транзакцией, до завершения текущей транзакции".

Ответ 1

Возможно, вам лучше настроить уровень изоляции транзакции, а не использовать подсказку запроса.

Следующая ссылка из Books Online содержит подробную информацию о каждом из разных уровней изоляции.

http://msdn.microsoft.com/en-us/library/ms173763.aspx

Вот хорошая статья, которая объясняет различные типы поведения блокировки в SQL Server и предоставляет примеры.

http://www.sqlteam.com/article/introduction-to-locking-in-sql-server

Ответ 2

подсказки таблицы

WITH (HOLDLOCK) позволяет другим читателям. UPDLOCK, как предлагается в другом месте, является эксклюзивным.

HOLDLOCK предотвратит другие обновления, но они могут использовать данные, которые обновляются позже.

UPDLOCK не позволит никому читать данные до тех пор, пока вы не совершите или откатите.

Вы посмотрели sp_getapplock? Это позволит вам сериализовать этот код (если это единственный бит обновления) без блокировки UPDLOCK

Изменить: проблема заключается в основном в этом коде, выполняющемся в двух разных сеансах. С помощью HOLDLOCk или REPEATABLE_READ данные будут прочитаны во втором сеансе до обновления первого сеанса. С помощью UPDLOCK никто не может читать данные в любой сессии.

Ответ 3

MSSQL:

SELECT id
FROM Inventory (UPDLOCK)
WHERE material_id = 25 AND quantity > 10;

http://www.devx.com/tips/Tip/13134



По любым причинам вас интересует PostgreSQL:
SELECT id
FROM Inventory    
WHERE material_id = 25 AND quantity > 10
FOR UPDATE;

Ответ 5

С UPDLOCK, HOLDLOCK