我在多用户系统和一个存储过程中并发,如下所示:
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
...在相同查询的另一个连接中获得预期结果