【问题标题】:Why would this stored proc not work right once in a while?为什么这个存储过程有时不能正常工作?
【发布时间】: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


【解决方案1】:

不要使用 ROWLOCK 提示,而是在将isolation_level 设置为SERIALIZABLE 的情况下运行更新。

此外,如果您在更新中使用 OUTPUT 子句,您可以在更新完成后立即获得受影响行的列表。这意味着您可以更快地结束您的事务 1 DML 语句并保持您的 ACIDity。

【讨论】:

    【解决方案2】:

    这可能是你的问题吗?

    在事务中指定时 在 SNAPSHOT 隔离下运行 级别,不采取行锁,除非 ROWLOCK 与其他表结合 需要锁的提示,例如 UPDLOCK 和 HOLDLOCK。

    Source

    【讨论】:

      猜你喜欢
      • 2020-09-19
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-30
      • 2023-02-20
      • 1970-01-01
      • 2022-10-23
      相关资源
      最近更新 更多