2009-01-30 33 views
16

我想要實現像原子事務如下:我應該使用哪種鎖定提示(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子句中使用什麼鎖定提示來防止在完成更新和提交事務之前更改選定的庫存記錄?

編輯: 非常感謝約翰,好的解決方案似乎是將事務隔離級別設置爲REPEATABLE READ。這將確保「在當前事務完成之前,沒有其他事務可以修改已被當前事務讀取的數據」。

+0

好問題...我將要工作的一些代碼,完全適合這個標準很快......我甚至沒有意識到這是一個問題:) – 2009-01-30 20:29:34

+0

謝謝安德魯!事實上,如果數據或者交易使用的假設在處理過程中發生了變化,那麼交易並不會真正產生一致的結果。 – Daniel 2009-01-30 20:55:19

回答

0

我相信這會是UPDLOCK。

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

+0

請記住,在SQL Server 2005及更高版本中,鎖定不會以這種方式運行。這篇文章相當過時。 – 2009-01-30 20:22:03

+0

我正在使用SQL Server 2005. – Daniel 2009-01-30 20:23:02

0

與UPDLOCK,HOLDLOCK

+1

爲什麼需要HOLDLOCK? – Daniel 2009-01-30 20:20:15

2

table hints

WITH (HOLDLOCK)允許其他讀者。 正如其他地方所建議的UPDLOCK是排他性的。

HOLDLOCK將阻止其他更新,但它們可能會使用稍後更新的數據。

UPDLOCK將阻止任何人讀取數據,直到您提交或回滾。您是否看過sp_getapplock? 編輯:問題主要在於此代碼在2個不同的會話中運行,這將允許您在沒有UPDLOCK阻止的情況下對此代碼進行序列化(如果它是唯一的更新位)

編輯: 使用HOLDLOCk或REPEATABLE_READ,將在第一次會話更新之前在第二次會話中讀取數據。使用UPDLOCK,任何人都無法讀取任何會話中的數據。

2

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;