【发布时间】:2011-03-02 04:30:56
【问题描述】:
我有一个名为“Schedule”的表,它用作多个进程/计算机频繁访问该表的队列机制。 proc 的目标是拾取行数不超过@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
【问题讨论】:
-
更新语句运行多长时间后才能选择?
-
我想我知道你要去哪里了。更新非常非常快,但时间也非常接近。但是,事务不应该不允许同时更新同一行吗?
标签: sql-server stored-procedures azure-sql-database