解决 SQL Server 订单处理队列中的竞争条件
挑战:通过存储过程访问订单队列的并发订单处理器会遇到竞争条件。这会导致重复订单检索和处理错误。 当前的存储过程尝试通过一次锁定 20 个订单来缓解此问题,但这证明是不够的。
有问题的查询:
原始查询使用带有行锁定的两步过程(UPDATE 后跟 SELECT),为竞争条件创建一个窗口:
<code class="language-sql">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</code>
根本原因: UPDATE 语句在 SELECT 语句识别行之后尝试锁定行。 在多处理器环境中,这种时序差异允许多个处理器获取相同的订单。
有效的解决方案:在单个 语句中使用 READPAST
和 UPDLOCK
提示可以解决竞争条件。 UPDATE
允许 UPDATE 的 SELECT 部分绕过锁定的行,而 READPAST
确保仅更新未锁定的行。UPDLOCK
修改后的查询:
这种简化的方法消除了竞争条件:
<code class="language-sql">UPDATE TOP (20) OrderTable SET ProcessorID = @PROCID FROM OrderTable WITH (ROWLOCK, READPAST, UPDLOCK) WHERE ProcessorID = 0</code>
以上是如何防止 SQL Server 订单处理队列中的竞争条件?的详细内容。更多信息请关注PHP中文网其他相关文章!