我在多用户系统和一个存储过程中并发,如下所示:

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


...在相同查询的另一个连接中获得预期结果

10-04 17:53