我有一张任务表。多个用户同时尝试获取任务。这个修剪过的查询是我逻辑的核心:
; WITH TASKS_CTE AS (
SELECT TOP(1) T.TASK_ID AS TASK_ID,
T.ASSIGNED_USER_CODE AS ASSIGNED_USER_CODE,
T.STATUS AS STATUS
FROM TASK T WITH (ROWLOCK,READPAST)
JOIN TASK_SCORE TS WITH (NOLOCK) ON TS.TASK_ID = T.TASK_ID
WHERE
T.STATUS = 0
ORDER BY TS.TOTAL_SCORE DESC
)
UPDATE TASKS_CTE
SET STATUS = 1,
ASSIGNED_USER_CODE = @USER_CODE,
OUTPUT INSERTED.TASK_ID, INSERTED.ASSIGNED_USER_CODE, INSERTED.STATUS INTO @NEXT_TASK_TABLE;
我省略了检查@@ ROWCOUNT以查看某个任务是否已成功登记的部分。
事实证明,(ROWLOCK, READPAST)
并未阻止多个用户获得相同的任务。我在SO上提到了这两个问题,在SQL Server Process Queue Race Condition中建议指定(ROWLOCK, READPAST, UPDLOCK)
。另一方面,建议Using a database table as a queue (UPDLOCK, READPAST)
。
因此我的问题是,为了实现多客户端队列,除了ROWLOCK
之外还需要指定(UPDLOCK, READPAST)
吗? (UPDLOCK, READPAST)
和(UPDLOCK, READPAST, ROWLOCK)
之间的确切区别是什么?
答案 0 :(得分:1)
ROWLOCK是为了确保锁升级仅限于一行。这是您希望帮助确保以正确的顺序处理队列的内容。在这个例子中这是一个很好的做法。