Какие подсказки блокировки я должен использовать (T-SQL)? - PullRequest
17 голосов
/ 30 января 2009

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

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. Это гарантирует, что «никакие другие транзакции не могут изменять данные, прочитанные текущей транзакцией, до тех пор, пока текущая транзакция не завершится».

Ответы [ 5 ]

12 голосов
/ 30 января 2009

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

Следующая ссылка от 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 голосов
/ 30 января 2009

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;
2 голосов
/ 30 января 2009

настольные подсказки

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

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

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

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

Редактировать: Проблема заключается в основном в том, что код выполняется в 2 разных сеансах. При использовании HOLDLOCk или REPEATABLE_READ данные будут считаны во 2-м сеансе до обновления 1-го сеанса. С UPDLOCK никто не может читать данные в любом сеансе.

0 голосов
/ 30 января 2009

Блокировка подсказок:

WITH (UPDLOCK, HOLDLOCK)
0 голосов
/ 30 января 2009

Я считаю, что это будет UPDLOCK.

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

...