您的工作表是一个队列。众所周知,编写用户表备份队列很容易出错,因为这会导致死锁和并发问题。
最简单的事情是删除用户表并使用真实队列。这将使您在经过系统测试和验证的代码库上获得无死锁且无并发的队列。问题在于,围绕队列的整个范例从INSERT和DELETE / UPDATE更改为SEND /RECEIVE。另一方面,使用内置队列,您可以获得一些非常强大的免费功能,即激活和相关项锁定。
如果要继续沿用户表支持队列的路径前进,那么编写用户表队列的 最重要的技巧是使用UPDATE … OUTPUT:
WITH cte AS (
SELECT TOP(20) status, id, ...
FROM table WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE status = 'new'
ORDER BY enqueue_time)
UPDATE cte
SET status = 'processing'
OUTPUT
INSERTED.id, ...
CTE语法只是为了方便正确放置TOP和ORDER BY,可以使用派生表同样方便地编写查询。您不能使用直接UPDATE … TOP,因为UPDATE不支持ORDER BY,并且您需要使用它来满足需求中“最旧的”部分。需要使用锁提示来促进并行处理线程之间的高度并发性。
我说这是第二个最重要的把戏。最重要的是如何组织表格。对于队列,它 由聚类(status, enqueue_time)
。如果您没有正确地组织表格,那么最终将导致死锁。先发制人的评论:在这种情况下碎片是无关紧要的。