我在多用户系统和存储过程中有一个并发,如下所示:
CREATE PROCEDURE dbo.GetWorkitemID
AS
DECLARE @workitem int;
UPDATE workqueue
SET status = 'InProcess', @workitem = workitemid
WHERE workitemid = (SELECT TOP 1 workitemid
FROM workqueue WITH (ROWLOCK,UPDLOCK,READPAST)
WHERE status = 'New' ORDER BY workitemid)
SELECT @workitem
GO
它将单个记录状态从“新建”更新为“处理中”并返回记录的 ID。
问题如下:我应该在事务范围内使用此存储过程来启用 ROWLOCK、UPDLOCK 等吗?是必须的吗?第二:它真的是线程安全的并且保证唯一性吗?
最佳答案
这是运行“表作为队列”的正确方法
请参阅:SQL Server Process Queue Race Condition您不需要交易
这既是线程安全又是并发安全的
编辑:
作为 Filip De Vos 的反例
注意使用覆盖索引和 UPDLOCK 而不是 XLOCK 和相同的查询
DROP table locktest
create table locktest (id int, workitem int, status varchar(50))
insert into locktest (id, workitem) values (1, 1), (2,2), (3,3)
create index ix_test2 on locktest(workitem) INCLUDE (id, status)
--When I run this on one connection
begin tran
select top (1) id, status
from locktest with (rowlock, updlock, readpast)
ORDER BY workitem
...我在具有相同查询的另一个连接中得到了预期结果
关于sql-server - tsql:存储过程和行锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6979383/