2010-08-04 86 views
2

編輯:SQL Server 2005適用於此場景的可序列化事務?

我有一個客戶應用程序運行在5個獨立的服務器上。每個應用程序正在查看一個調度表。我想確保沒有機器可以像任何其他機器一樣同時訪問相同的記錄。每臺服務器一次只能處理1行。基本上,應用程序只是選擇可以運行的下一個記錄。如果沒有選擇,它什麼都不做,等待另一分鐘,然後再試。

[編輯:更具體地說,沒有行從dbo.the_table中刪除。它只是標誌着IsProcessing = 1,使其他的機器將無法挑選了]

我的存儲過程(SQL Server)的是如下:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
BEGIN TRAN 

SET @ScheduleId = SELECT TOP 1 ScheduleId FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1 

UPDATE dbo.the_table SET IsProcessing=1 WHERE ScheduleId = @ScheduleId 

--Edit: Return this to the program so we can do stuff with the data 
SELECT * FROM dbo.the_table WHERE ScheduleId = @ScheduleId 

IF @@ERROR = 0 
COMMIT TRAN 
ELSE 
ROLLBACK TRAN 

我想肯定的是,雖然交易是在進度,其他機器的任何SELECT語句都將被阻塞,直到事務被阻塞事務提交。 (例如,機器A啓動事務 - 如果B,C,D或E嘗試並選擇,它們將等待,直到事務提交)。

回答

4

你在什麼版本的SQL Server?如果SQL2005 +你可以做到這一切在一個聲明

;WITH s AS 
(
SELECT TOP 1 * 
FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1 
AND IsProcessing = 0 /*?*/ 
--ORDER BY ScheduleId ? 
) 
UPDATE s WITH (ROWLOCK, READPAST) 
SET  IsProcessing=1 
OUTPUT INSERTED.* /*Return row that was updated*/ 
+3

+1此外,我建議去http://rusanu.com/2010/03/26/using-tables-as-queues/因爲'在這種情況下,the_table'被用作隊列。 – 2010-08-04 00:12:57

+0

我非常抱歉。我錯過了程序的一個重要部分。我做了適當的編輯。 – 2010-08-04 00:24:36

+1

@Remus,謝謝非常有用的鏈接。 @Zero - 就我所見,可以通過返回'INSERTED。*'並讓程序選擇檢查'IsProcessing = 0'的行來容易地解決 - 或者我錯過了什麼? – 2010-08-04 00:34:27