我有一系列需要以原子方式运行的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;
答案 0 :(得分:7)
在这种情况下,
这两个概念是不同的,也不是你想要的。
要执行您想要的操作,要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
答案 1 :(得分:2)
您正在描述典型的队列处理,既不需要tablockx也不需要序列化,也不会实际工作。我建议你过去Using tables as Queues进行部门讨论,讨论可行的和不可行的。它的要点是: