我有一个订单队列,多个订单处理器通过存储过程访问该队列。每个处理器都会传递一个唯一的 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
Edit:
我用谷歌搜索来检查我的答案:“使用 READPAST 和 UPDLOCK 处理 SQL Server 中的数据队列” http://www.mssqltips.com/tip.asp?tip=1257。我已经很多年没有阅读并使用这个解决方案了。
原来的:
如果您使用 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 子句更优雅地完成此操作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)