2013-09-26 225 views
3

我發出帶有施加UPDLOCK以下查詢:SqlServer時,是UPDLOCK應用中選擇

select @local_var = Column 
from table (UPDLOCK) 
where OtherColumn = @parameter 

什麼情況是,多個連接打這個例程用於在存儲過程中,計算一個唯一的ID。一旦鎖獲取我們計算下一個id,更新行中的值並提交。這是因爲客戶端對其系統中某些對象ID有特定的格式要求。

UPDLOCK鎖定正確的行並阻止其他進程,但是每隔一段時間我們會得到一個重複的id。似乎局部變量在行被鎖定之前被賦予當前值。我曾假設在處理陳述的選擇部分之前會獲得鎖定。我使用的是SQLServer 2012,隔離級別設置爲讀提交。

如果需要其他信息,請讓我知道。或者如果我正在做一些明顯愚蠢的事情,那麼這些信息也是受歡迎的。

+0

的可能的複製[UPDLOCK,HOLDLOCK](http://stackoverflow.com/questions/7843733/confused-about-updlock-holdlock) –

+0

我的問題是不是一般來說,UPDLOCK是關於什麼時候SQL語句的選擇部分與獲得記錄鎖定或在等待鎖定時進行阻塞有關的評估。由於它是單個語句的一部分,我期望(對或錯)在獲取鎖之前不會評估選擇。 –

回答

2

SQL Server documentation on UPDLOCK

使用更新鎖而不是共享鎖,而讀一臺,並保持鎖定直到語句或事務結束。 UPDLOCK的優點是可以讀取數據(不會阻擋其他讀取器)並稍後進行更新,並確保數據自上次讀取後未發生更改。

這意味着其他進程仍然可以讀取值。

嘗試使用XLOCK代替,它會鎖定其他讀數。

+0

我認爲問題是其他進程是否可以使用相同的SELECT語句讀取相同的值。由於第二個進程會嘗試獲取UPDLOCK,因此應該阻止執行SELECT,直到第一個完成其UPDATE,對吧? –

+0

我遇到的實際問題是,在獲取鎖之前發生了@local_var分配,並沒有阻止所以其中一個呼叫者獲得了舊值。我期待這個區塊能夠在任務完成之前適用於整個聲明。 –

+0

我認爲你有錯誤的方法。我認爲這項任務是在獲得鎖定之後發生的,但在隨後的更新之前(請參閱我的答案) - 希望這有助於我,雖然我不是專家。 – MultiMat

0

我認爲問題在於您的鎖只在此選擇過程中進行。 因此,一旦你的存儲過程有價值,它會釋放鎖定,然後繼續更新id(或插入新行或其他)。

這意味着在Parallel中運行的另一個查詢能夠查詢相同的值,然後更新/插入同一行。

您應該添加一個HOLDLOCK到'with'語句中,以便鎖定時間更長。

這被視爲相當不錯在此Answer