小编典典

SQL Server进程队列竞争条件

sql

我有一个订单队列,可通过存储过程由多个订单处理器访问。每个处理器传递一个唯一的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

阅读 168

收藏
2021-05-05

共1个答案

小编典典

编辑:

我用谷歌搜索了我的答案:“使用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子句更优雅地完成此操作。

2021-05-05