除了(UPDLOCK,READPAST)提示之外,我还需要ROWLOCK吗?

时间:2016-01-15 08:27:23

标签: sql-server locking priority-queue race-condition

我有一张任务表。多个用户同时尝试获取任务。这个修剪过的查询是我逻辑的核心:

; 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)之间的确切区别是什么?

1 个答案:

答案 0 :(得分:1)

ROWLOCK是为了确保锁升级仅限于一行。这是您希望帮助确保以正确的顺序处理队列的内容。在这个例子中这是一个很好的做法。