У меня есть таблица с именем «Расписание», которая служит механизмом очереди для нескольких процессов / компьютеров, часто посещающих таблицу.
Цель процедуры состоит в том, чтобы выбрать строки не более @count строк, которые могут быть выбраны (их LastCompletedProcessingId и LastStartedProcessingId должны совпадать) и пометить их как выбранные (изменить LastStartedProcessingId на NEWID ()), поэтому что следующий процесс не пытается выбрать уже отмеченные строки.
Моя проблема заключается в том, что в редких случаях, когда proc вызывается в очень близкое время несколькими клиентами, несколько клиентов в конечном итоге получают одинаковые строки. Как это возможно? Как мне этого избежать? Сам стол не огромный. @ 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