【问题标题】:TABLOCKX versus SERIALIZABLETABLOCKX 与 SERIALIZABLE
【发布时间】:2011-02-07 18:17:14
【问题描述】:

我有一系列需要以原子方式运行的 T-SQL 查询。 (见下文)...目的是允许 1 个用户一次检索一个唯一的行,并防止其他用户同时检索同一行。

到目前为止,我已经看到了两种可能的解决方案。 1) 表提示 (HOLDLOCK, TABLOCKX) 和 2) 事务隔离级别 (SERIALIZABLE)...

我的问题:

  1. 哪个选项更好?

  2. 还有其他/更好的解决方案吗?

DECLARE @recordId int;

SELECT @recordId = MIN([id])
FROM Exceptions
WHERE [status] = 'READY';

UPDATE Exceptions
SET [status] = 'PROCESSING',
    [username] = @Username
WHERE [id] = @recordId;

SELECT *
FROM Exceptions
WHERE [id] = @recordId;

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    在这种情况下,

    • HOLDLOCK = SERIALIZABLE = 持续时间、并发
    • TABLOCKX = 排他表锁

    这两个概念是不同的,也不是你想要的。

    要做你想做的,到avoid race conditions,你需要强制一个非阻塞(READPAST)独占(UPDLOCK)行级(ROWLOCK)锁。您还可以使用 OUTPUT 子句使其成为原子的单个语句。这可以很好地扩展。

    UPDATE
        E
    SET
       [status] = 'PROCESSING', [username] = @Username
    OUTPUT
       INSERTED.*
    FROM
       (
        SELECT TOP 1 id, [status], [username]
        FROM Exceptions (ROWLOCK, READPAST, UPDLOCK)
        WHERE [status] = 'READY'
        ORDER BY id
       ) E
    

    一般来说,锁有3个方面

    • 粒度 = 锁定内容 = 行、页、表 (PAGLOCK, ROWLOCK, TABLOCK)
    • 隔离级别 = 锁定持续时间、并发 (HOLDLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE)
    • 模式 = 共享/独占 (UPDLOCK, XLOCK)

    • “组合”例如NOLOCK, TABLOCKX

    【讨论】:

      【解决方案2】:

      您描述的是典型的队列处理,既不需要 tabblockx,也不需要 serializable,它们也不会实际工作。我建议您通过Using tables as Queues 深入讨论什么是可能的,什么不是。它的要点是:

      • 选择适当的集群键(关键!)
      • 使用 OUTPUT 子句
      • 使用 READPAST

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多