我有一系列需要原子运行的 T-SQL 查询。 (见下文)...目的是允许 1 个用户一次检索单个唯一行,并防止其他用户同时检索同一行。
到目前为止,我已经看到了两种可能的解决方案。 1) 表提示(HOLDLOCK、TABLOCKX)和 2)事务隔离级别(SERIALIZABLE)...
我的问题:
哪个选项更好?
还有其他/更好的解决方案吗?
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;
最佳答案
在这种情况下,
- 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
关于sql - TABLOCKX 与 SERIALIZABLE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4924861/