2015-10-16 160 views
1

這是更多的知識共享帖子。SQL計數器遞增併發問題 - 選擇/更新問題

最近在我的一個項目中,我遇到了一個很常見的問題,但直到遇到它時才真正給它一個想法。 有很多解決方案可用,但不知何故,我沒有找到我正在尋找的那個,我將在這篇文章中分享。我相信你們中的許多人已經知道下面的解決方案,但對於那些不這樣做的人肯定可以成爲救命的人。 :-)

問題:

最近,我正在開發一個windows服務。這項服務應該將一些記錄插入一個長期存在並被其他幾個舊服務使用的表中。有一個列(稱爲「ID」),它包含一個整數值。拿到整數插入到該表中寫入(可能是年前)的邏輯如下陳述:

邏輯:

  1. 從表中讀取的值(假設表1 - 名稱/值對),
  2. 增量它由1
  3. 更新的值和
  4. 最後得到新的值[/亮點。

代碼

SELECT @value = [Value] from [dbo].[Table1] WHERE [Name] = @Name; 
UPDATE [dbo].[ Table1] SET [Value] = @value +1 WHERE [Name] = @Name; 
SELECT @value = @value+1; 

使用該技術具有重大的併發問題。

    由多個線程讀取
  1. 值相同
  2. 死鎖問題

什麼是解決這種問題的最好辦法 - 考慮到這是在許多不同的應用程序/服務的簡稱?

+3

您可以編輯問題,以便它只包含問題,並與您的解決方案創建一個單獨的答案?請參閱[我可以回答我自己的問題?](http://stackoverflow.com/help/self-answer)瞭解更多信息。 – sstan

+0

也許可以添加一些文檔鏈接,那是什麼'OUTPUT插入',這是所有rdbms或特別是一個? –

+0

附件在哪裏? –

回答

1

的分辨率

思路清晰,將擺脫這片和重寫此。但是有時候,特別是當你在這樣的領域工作時,某些邏輯,表格,代碼已經被其他幾個程序引用,這不是一個簡單的調用。

我的目標是攻擊問題的根源並擺脫它。如果我能做到這一點,應該沒有真正的影響。 proc的輸出結果是一樣的,所以對外界來說沒有任何變化。 :-)

因此,我對上述語句做了一些小的調整,以確保每個線程更新值並讀取更新的值。沒有更多的衝突,沒有更多的髒讀。

更新的代碼

DECLARE @table table(
    Value int NOT NULL 
); 

-- Update the value and output the same into a local table variable 
UPDATE [dbo].[Table1] SET [Value] = [Value] + 1 OUTPUT inserted.[Value] INTO @table 
WHERE [Name] = @Name 

-- Now read the value from the local table variable 
SELECT Value FROM @table; 

有關output子句檢查https://msdn.microsoft.com/en-us/library/ms177564(v=sql.90).aspx

更多信息,我跑了一些測試與並行。每次(20,000次)。我的測試表有兩個項目 -

  1. 名稱=第一個和值= 1 - 20000更新後的值應爲20001
  2. 名稱=其次,值= 100 - 20000更新後的值應爲20,100

如果你檢查附件,你會發現數字的差異。

TestResults

死鎖問題是難以重現,但隨着多線程的測試結果讀顯而易見的值相同的問題。

任何想法都是值得歡迎的。

正如我剛纔所說,很多人已經知道這個解決方案,但對於那些不這樣做的人來說,這肯定會節省一些時間。 :-)

+0

您見過[在併發環境中處理最大(ID)](http://stackoverflow.com/q/7539997/ 1115360)? –

+0

是的,現在。感謝分享。 – Sourav