I have a table of tasks. Multiple users simultaneously try to get a task. This trimmed query is the heart of my logic:
; 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;
I omitted the part where @@ROWCOUNT is checked to see if a task was successfully dequeued.
Well it turns out that (ROWLOCK, READPAST)
is not preventing multiple users getting the same task. I came accross these two questions on SO, in SQL Server Process Queue Race Condition it is advised that (ROWLOCK, READPAST, UPDLOCK)
be specified. On the other hand, in Using a database table as a queue (UPDLOCK, READPAST)
is advised.
Hence my question, do i need to specify ROWLOCK
in addition to (UPDLOCK, READPAST)
in order to implement a multi-client queue? What exactly differs between (UPDLOCK, READPAST)
and (UPDLOCK, READPAST, ROWLOCK)
?