我有一個名爲「計劃」的表,它充當多個進程/計算機頻繁訪問表的隊列機制。 proc的目標是拾取行數不超過行數的計數,並有資格被拾取(它們的LastCompletedProcessingId & LastStartedProcessingId必須匹配)並將它們標記爲已拾取(將LastStartedProcessingId更改爲NEWID()),以便下一個進程不會嘗試拾取已標記的行。爲什麼這個存儲過程偶爾不能正常工作?
我的問題是,在很少的時候,當多個客戶端在非常近的時間調用過程時,多個客戶端會得到相同的行。這怎麼可能?我如何避免它?桌子本身並不大。 @timeout不是一個問題,因爲這些事情不會花費超過300秒的時間來處理,而且我有一個日誌,在進程讀取多個記錄之前,它們沒有運行超過300秒。這是運行在SQL Azure
任何想法如何這可能嗎? 謝謝
CREATE PROCEDURE X
@count int,
@timeout int = 300
AS
BEGIN
SET NOCOUNT ON;
DECLARE @batchId uniqueidentifier
SELECT @batchId = NEWID()
BEGIN TRAN
-- Update rows
UPDATE Schedule
WITH (ROWLOCK)
SET
LastBatchId = @batchId,
LastStartedProcessingId = NEWID(),
LastStartedProcessingTime = GETDATE()
WHERE
AccountId IN (
SELECT TOP (@count) AccountId
FROM Schedule
WHERE
(LastStartedProcessingId = LastCompletedProcessingId OR LastCompletedProcessingId IS NULL OR DATEDIFF(SECOND, LastStartedProcessingTime, GETDATE()) > @timeout) AND
(LastStartedProcessingTime IS NULL OR DATEDIFF(SECOND, LastStartedProcessingTime, GETDATE()) > Frequency)
ORDER BY (DATEDIFF(SECOND, LastStartedProcessingTime, GETDATE()) - Frequency) DESC
)
-- Return the changed rows
SELECT AccountId, LastStartedProcessingId, Frequency, LastProcessTime, LastConfigChangeTime
FROM Schedule
WHERE LastBatchId = @batchId
COMMIT TRAN
END
更新聲明在選擇之前運行多長時間? – Sergey 2011-03-02 04:36:13
我想我明白你要去哪裏。更新速度非常快,但時間也非常接近。但是,交易不應該允許同時更新到同一行嗎? – Igorek 2011-03-02 05:08:36