Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server进程队列竞争条件_Sql_Sql Server_Tsql_Queue_Race Condition - Fatal编程技术网

SQL Server进程队列竞争条件

SQL Server进程队列竞争条件,sql,sql-server,tsql,queue,race-condition,Sql,Sql Server,Tsql,Queue,Race Condition,我有一个订单队列,由多个订单处理程序通过存储过程访问。每个处理器传入一个唯一的ID,该ID用于锁定接下来的20个订单供自己使用。然后,存储过程将这些记录返回给订单处理器,以便对其执行操作 在某些情况下,多个处理器能够检索同一个“OrderTable”记录,,此时他们试图同时对该记录进行操作。这最终会导致在流程的后期抛出错误 我的下一步行动是允许每个处理器获取所有可用的订单,并循环处理处理器,但我希望简单地使这部分代码线程安全,并允许处理器随时获取记录 所以明确地说——任何关于我为什么会经历这种比

我有一个订单队列,由多个订单处理程序通过存储过程访问。每个处理器传入一个唯一的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提示,则将跳过锁定的行。您使用了ROWLOCK,因此应该避免锁升级。我发现你也需要升级锁

因此,进程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月


如果您需要一次选择和一次更新,那么可以使用OUTPUT子句更优雅地完成此操作。

您可以使用ServiceBroker。您还可以使用sp_getapplock序列化对行的访问—这将消除争用条件:

“通过创建自己的锁(SQL中的互斥锁)来协助并发”

很有趣……我将尝试添加一些真正有用的额外提示。不再重复。谢谢。我知道这很旧,但是
UPDATE
语句中的
UPDLOCK
提示是否在读取要更新的行时强制更新锁(而不是共享锁)?换句话说,如果不使用
UPDLOCK
,是否可能存在争用条件和两个update语句来选择相同的行?@NelsonRothermel:是的,因为否则它是共享/读取锁,两个进程可以读取,而readpass不会work@UriAbramson这只是猜测,但如果不使用ROWLOCK,然后进程1更新20行,但锁定超过20行(例如40行)。进程2更新20行,但跳过40行。因此,将错过20行!ROWLOCK表示仅锁定已更新的行。