我需要建立一個使用一些SQL表的隊列系統,如here所述。這之中,因爲我需要過濾的不同性判據排隊的項目,在存儲過程中,我使用ORDER BY AND WITH(ROWLOCK,UPDLOCK,READPAST)
BEGIN TRANSACTION
CREATE TABLE #Temp (ID INT, SOMEFIELD INT)
INSERT INTO #Temp SELECT TOP (@Something) TableA.ID, TableB.SomeField FROM TableA WITH (ROWLOCK, READPAST) INNER JOIN TableB WITH (UPDLOCK, READPAST) WHERE Condition1
INSERT INTO #Temp SELECT TOP (@Something) TableA.ID, TableB.SomeField FROM TableA WITH (ROWLOCK, READPAST) INNER JOIN TableB WITH (UPDLOCK, READPAST) WHERE Condition2
(...)
UPDATE TableB SET SomeField = 1 FROM TableB WITH (ROWLOCK, READPAST) WHERE ID IN (SELECT ID FROM #Temp)
COMMIT TRANSACTION
我在第二使用的第一臺ROWLOCK
和UPDLOCK
,因爲在此之後選擇,我將僅更新TableB
,但我需要確保這些行不會被任何其他併發查詢在TableA
中更新。一切都很順利,直到我需要在上面的任何一個SELECT
s中插入ORDER BY
子句爲止,這樣只有特定的ID纔會被選中(我必須真的這樣做)。發生什麼是:
1)沒有ORDER BY
,兩個併發執行按需要執行,返回不同且不重疊的結果;但是,他們不會返回我想要的結果,因爲那些準確的結果超出了每個SELECT
聲明的範圍。
2)使用ORDER BY
和兩個併發執行,只有第一個返回結果。第二個不返回任何東西。
我記得在博客上看到,對於使用WITH (ROWLOCK, READPAST)
和ORDER BY
工作的這類查詢,需要在排序中使用的字段上創建索引。我試過了,但我得到了同樣的結果。我怎樣才能克服這個問題?
編輯:舉例來說,如果我有一個表TestTable
與字段(TestID INT,價值INT)和值 「(1,1),(2,2),...」,並執行 「同步」
BEGIN TRANSACTION
SELECT TOP 2 TestID FROM TestTable WITH (UPDLOCK, READPAST)
WAITFOR DELAY '00:00:05'
COMMIT TRANSACTION
第一次執行返回行(1,2),第二次執行返回行(3,4)。但是,如果我執行
BEGIN TRANSACTION
SELECT TOP 2 TestID FROM TestTable WITH (UPDLOCK, READPAST) ORDER BY VALUE ASC
WAITFOR DELAY '00:00:05'
COMMIT TRANSACTION
第一個返回(1,2),第二個不返回任何內容。爲什麼是這樣?!