TSQL:存储过程和ROWLOCK
问题描述:
我有一个多用户系统和存储过程的并发性,如下图所示:TSQL:存储过程和ROWLOCK
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你并不需要一个交易
这既是线程和并发安全
编辑:
01在另一个连接作为一个反例菲利普德沃思的
注意,使用覆盖索引的和 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
...我得到预期的结果用相同的查询
答
这是不可靠的。因为你给的锁定提示就是这样,锁定提示。另外,根据表索引的方式,结果可能会有很大的不同。
例如:
create table test (id int, workitem int, status varchar(50))
insert into test (id, workitem) values (1, 1), (2,2), (3,3)
create index ix_test on test(workitem)
当我在一个连接
begin tran
select * from test with (rowlock, xlock, holdlock) where workitem = 1
运行这一点,我第二个连接上运行此:
select top (1) * from test with (rowlock, readpast) order by workitem
这将返回:
workitem
--------
3
相同的,如果我做的:
update top (1) test with (rowlock, readpast)
set status = 'Proc'
output inserted.workitem
所以,你可以用它来并发拿起你需要什么,但是这不是在订单并发处理的可靠方法。
答
我应该使用此存储过程中的事务范围...
在每一个SQL DML语句在事务的上下文中运行,无论你明确打开一个或没有。默认情况下,SQL Server在执行每条语句时将打开一个事务(如果没有打开),执行语句,然后提交事务(如果没有发生错误)或将其回滚。
受@Filip提醒(即仍无法保证项目的选择顺序),它将是安全的,并且每个调用将返回一个不同的行(如果有一个可用且未锁定)。
你的原始答案由链接? – johnny
@Johnny:是的,但我根据你的其他问题添加了一些东西 – gbn