TABLOCKX与SERIALIZABLE

Sam*_*Sam 4 sql t-sql sql-server

我有一系列需要以原子方式运行的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;
Run Code Online (Sandbox Code Playgroud)

gbn*_*gbn 7

在这种情况下,

  • HOLDLOCK = SERIALIZABLE =持续时间,并发
  • TABLOCKX =独占表锁

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

要执行您想要的操作,为了避免竞争条件,您需要强制执行非阻塞(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
Run Code Online (Sandbox Code Playgroud)

一般来说,锁具有3个方面

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

  • "合并",例如 NOLOCK, TABLOCKX