我有一个订单队列,可通过存储过程由多个订单处理器访问。每个处理器传递一个唯一的ID,该ID用于锁定接下来的20个订单以供自己使用。然后,存储过程将这些记录返回给要处理的订单处理器。
在某些情况下, 多个处理器能够检索相同的“ OrderTable”记录 ,此时它们将尝试同时对其进行操作。这最终会导致在该过程的后期引发错误。
我的下一个动作是允许每个处理器抓住所有可用的订单,然后对处理器进行轮循,但是我希望简单地使这一部分代码线程安全,并允许处理器在需要时随时抓取记录。
如此明确-任何想法我为什么会遇到这种比赛情况以及如何解决问题。
BEGIN TRAN UPDATE OrderTable WITH ( ROWLOCK ) SET ProcessorID = @PROCID WHERE OrderID IN ( SELECT TOP ( 20 ) OrderID FROM OrderTable WITH ( ROWLOCK ) WHERE ProcessorID = 0) COMMIT TRAN SELECT OrderID, ProcessorID, etc... FROM OrderTable WHERE ProcessorID = @PROCID
编辑:
我用谷歌搜索了我的答案:“使用READPAST和UPDLOCK在SQL Server中处理数据队列”。自从我了解并使用此解决方案已有好几年了。
原版的:
如果使用READPAST提示,则将跳过锁定的行。您已使用ROWLOCK,因此应避免锁升级。正如我所发现的,您还需要UPDLOCK。
因此,进程1锁定20行,进程2锁定接下来的20行,进程3锁定41至60行,依此类推
更新也可以这样写:
UPDATE TOP (20) foo SET ProcessorID = @PROCID FROM OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK) WHERE ProcessorID = 0
刷新,2011年10月
如果您需要一次性执行SELECT和UPDATE的操作,则可以使用OUTPUT子句更优雅地完成此操作。