SQL Server 进程队列竞争条件

标签 sql sql-server tsql queue race-condition

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

最佳答案

编辑:

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

关于SQL Server 进程队列竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/939831/

相关文章:

sql - 将 SQL SUM 与包含内部 SELECT 的 Case 语句一起使用

sql - 比较两个表并找出缺失的组合

mysql - 当我执行 INSERT 时,MySQL 内部会发生什么?

sql - 在单独的表中显示相互链接的数据

sql - Oracle sql 正则表达式

SQL Server 高 CPU 和 I/O 事件数据库调整

c# - 重用 SqlDataRecord 是否安全?

sql-server - 在 SQL Server 中转义字符串,以便在 LIKE 表达式中安全使用

sql-server - SQL Server 中 ASSEMBLIES 的用途是什么?

sql - SQL 服务器查询中的 NULL 值