你的表的工作是一個隊列。編寫用戶表備份隊列是一個衆所周知的錯誤,因爲它會導致死鎖和協調問題。
最簡單的事情是放棄用戶表並使用真實的queue來代替。這將爲您在系統測試和驗證的代碼庫上提供無死鎖協議的空閒隊列。問題是隊列周圍的整個範例從INSERT和DELETE/UPDATE變爲SEND/RECEIVE。另一方面,通過內置隊列,您可以獲得一些非常強大的免費禮品,即Activation和correlated items locking。
如果你想繼續向下用戶表支持隊列的路徑,則第二最重要的技巧以書面用戶表隊列是使用UPDATE ... OUTPUT:
WITH cte AS (
SELECT TOP(20) status, id, ...
FROM table WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE status = 'new'
ORDER BY enqueue_time)
UPDATE cte
SET status = 'processing'
OUTPUT
INSERTED.id, ...
的CTE語法只是爲了方便地放置TOP和ORDER BY,查詢可以使用派生表進行編寫,就像esily一樣。你不能使用直接更新...TOP,因爲UPDATE不支持ORDER BY,並且你需要這個來滿足你的需求中「最古老」的部分。需要鎖提示以促進並行處理線程之間的高度一致性。
我說這是第二重要的把戲。最重要的是你如何組織桌子。對於隊列,其必須由(status, enqueue_time)
聚類。如果你沒有正確地組織表格,最終會導致死鎖。先發制人的評論:在這種情況下,碎片是相當重要的。
即使在使用3個提示後,您是否可以解釋爲什麼如果表未由(status,enqueue_time)聚簇,會出現死鎖? – 2012-06-22 05:14:28
我不知道OUTPUT子句,它與提示一起提供了一個完整的解決方案。這在SO上回答了我自己的問題。 – 2012-11-09 14:23:07