我有一个存储过程如下:
CREATE PROCEDURE [dbo].[RV_SM_WORKITEM_CHECKWORKBYTYPE]
(
@v_ServiceName Nvarchar(20)
,@v_WorkType Nvarchar(20)
,@v_WorkItemThreadId nvarchar(50)
)
AS BEGIN
;WITH updateView AS
(
SELECT TOP 1 *
FROM rv_sm_workitem WITH (UPDLOCK)
WHERE stateofitem = 0
AND itemtype = @v_worktype
ORDER BY ITEMPRIORITY
)
UPDATE updateView
SET assignedto = @v_ServiceName,
stateofitem = 1,
dateassigned = getdate(),
itemthreadid = @v_WorkItemThreadId
OUTPUT INSERTED.*
END
它完成了我需要它做的工作,即获取具有最高优先级的1条记录,将其状态从Available(0)更改为Not-Available(1),并返回要完成的工作记录。我应该能够有很多线程(20个以上)使用这个proc并让所有20个线程不断运行/抓取一个新的工作项目。但是我发现超过2个线程,添加线程正在等待锁;我猜测UPDLOCK正在造成这种情况。
我有两个问题,有更好的方法吗?
我可以在没有cte中的UPDLOCK的情况下执行此操作,因为默认情况下update语句使用UPDLOCK吗?请注意,在任何给定时间,此表中都有超过400,000条记录。
答案 0 :(得分:0)
我必须做类似的事情,这就是我的建议:
AS BEGIN
DECLARE @results table (id int, otherColumns varchar(50))
WHILE (EXISTS(SELECT TOP 1 * FROM @results))
BEGIN
;WITH updateView AS
(
SELECT TOP 1 *
FROM rv_sm_workitem
WHERE stateofitem = 0
AND itemtype = @v_worktype
ORDER BY ITEMPRIORITY
)
UPDATE updateView
SET assignedto = @v_ServiceName,
stateofitem = 1,
dateassigned = getdate(),
itemthreadid = @v_WorkItemThreadId
OUTPUT INSERTED.* into @results
where stateofitem = 0
END
END
这可确保调用不允许对项进行双重处理。 (因为update语句中的where子句)。
这个想法有其他变化,但这是传达它的简单方法。这不是生产就绪代码,因为它会在while循环中不断循环,直到有东西要处理。但我留给你决定如何突破或不循环并返回空(并让客户端代码处理它。)
以下是我遇到此问题时帮助我的answer。