2011-03-01 62 views
1

經典的生產者 - 消費者問題。使用SQL Server和ASP.NET的生產者 - 消費者問題

我有x個應用程序服務器在DB表(相同的數據庫)中寫入記錄。

在每臺服務器上運行一個服務,該服務輪詢數據庫表,應該讀取最舊的條目,處理它並刪除它。 現在的問題是服務進入競爭狀態:服務器A上的服務開始讀取,服務器B開始讀取相同的記錄。我有點卡住這個......我經常實施生產者 - 消費者,但從來沒有跨越服務器壁壘。

除了在數據庫之外,服務器不能相互通話。

環境是SQL Server 2005和ASP-NET 3.5。

+0

如何在表中添加處理標誌以有效鎖定行,以便在特定服務器正在處理該行時進行處理。 – Andrew 2011-03-01 07:56:55

回答

4

如果你在一個事務性的方式拿起工作,只有一臺服務器可以把它撿起來:

set transaction isolation level repeatable read 

update top 1 tbl 
set  ProcessingOnServer = HOST_NAME() 
from YourWorkTable tbl 
where ProcessingOnServer is null 
     and Done = 0 

現在您可以選擇的細節,知道工作項被安全地分配給你:

select * 
from YourWorkTable tbl 
where ProcessingOnServer = HOST_NAME() 
     and Done = 0 

函數host_name()返回客戶端名稱,但如果您認爲它更安全,則可以從客戶端應用程序傳入主機名。

我們通常會添加一個時間戳,以便您可以檢查花費太長時間處理項目的服務器。

+0

但是,如果不事先更新並直接讀取,那麼是否就足以「設置事務隔離級別可重複讀取」? – Krumelur 2011-03-01 08:08:55

+0

@Krumelur:嗯不,因爲其他進程可以同時讀取。事務以'begin transaction'開始,但在實際讀取或寫入表之前它仍不會獲取鎖。 – Andomar 2011-03-01 14:24:37

+0

我不明白。在你的例子中,我沒有看到「開始交易」...? – Krumelur 2011-03-01 21:01:36