2011-11-01 73 views
5

我想:從表中的SQL選擇行和更新相同的行

    從處理的表格,其中標誌= 0
  1. 利用這些值都在第二表中的一些工作
  2. 選擇N行N行
  3. 更新這些N行,並設置標誌= 1

我有並行處理這樣做同樣的工作在一起,我想,以確保所有得到的唯一行的工作。我如何確保?

回答

5

我假設你在SQL Server上運行(由於標籤),如果不是,那麼我的答案是不適用的。 單獨鎖定是不夠的。如果使用數據庫記錄鎖定,SqL服務器將阻止其他進程嘗試訪問鎖定的行,實際上,您一次只能處理一行。 您的解決方案是將行鎖定與READPAST提示組合在一起,以便其他人鎖定的行將被跳過。以下是各過程中應做到:

  1. 選擇下一個解鎖的行進行處理,並鎖定
  2. 做的工作
  3. 更新該行並結束交易

select top 1 id, ... from TheTable with (updlock, readpast) where flag = 0

//do the work now

update TheTable set flag = 1 where id=<previously retrieved id>

這裏的好處是,選擇下一個解鎖行並鎖定它的操作是原子操作,因此它保證沒有其他人能夠選擇相同的行。

+0

READPAST提示是否有用,一篇好文章http://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in-sql-server-with-readpast-and-updlock/ – newbie

+0

隨着SQL 2008 ,您可以在查詢中使用OUTPUT子句和READPAST HINT將隊列操作組合到一個語句中.http://www.sqlservercentral.com/articles/Queue+processing/69653/ – newbie

+0

@newbie是的,您可以使用輸出來鎖定和檢索消息並將其標記爲在單個查詢中處理。但我一直在比較單個消息處理的性能,並且與兩個查詢相比沒有收穫(先選擇然後更新)。實際上,使用OUTPUT查詢時,多線程吞吐量稍低一些。也許在批處理中,Output子句會更快,但是對於單個消息來說不是這樣。 – nightwatch

0

一種方法是讓主程序向子線程分發段。

另一種方法是鎖定表格,獲得CEIL(N/#processes)行,其中flag = 0,將標誌更新爲2,然後釋放鎖定。然後下一個進程將會繼續執行,因爲flag = 2,它不會得到這些行。

你有兩種方法來鎖定表 - 你可以鎖定整個事情,或者做一個限制的SELECT ... FOR UPDATE(不要得到太多的行)。參見:SELECT FOR UPDATE with SQL Server

甚至比設置標誌爲2更好的標誌設置爲process_id。然後,您只需更新所有行以分配數字,然後讓流程開始工作,每個流程只檢查自己的行。

相關問題