2009-06-02 44 views
36

我有一个通过存储过程被多个订单处理器访问的订单队列。每个处理器都会传入一个唯一的ID,用于锁定下一个20个订单以供自己使用。存储过程然后将这些记录返回给订单处理器以执行操作。SQL Server进程队列争用条件

有些情况下,多处理器能够检索相同的'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 
+4

@Keltex

:很显然,他想知道如何重写此存储过程,以便它不会导致两个处理器处理相同的记录。 – Welbog 2009-06-02 14:30:49

回答

48

编辑:

我用Google搜索来检查我的回答:"Processing Data Queues in SQL Server with READPAST and UPDLOCK"。自从我阅读并使用该解决方案已经有数年了。

原文:

如果您使用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子句更优雅地完成此操作。

+0

有趣...我会试试这个 – 2009-06-02 15:40:08