Skip to content Skip to sidebar Skip to footer

How Do I Use Locking Hints So That Two Parallel Queries Return Non-intersecting Results?

I have an SQL table Tasks with columns Id and State. I need to do the following: find any one task with state ReadyForProcessing, retrieve all its columns and set its state to Proc

Solution 1:

This should do the trick.

BEGIN TRANSACTION
DECLARE@taskIdSELECT TOP (1) @taskid= TaskId FROM Tasks WITH (UPDLOCK, READPAST) WHERE State ='ReadyForProcessing'UPDATE Tasks SET State ='Processing'WHERE TaskId =@taskidCOMMIT TRAN

Solution 2:

what about something like this:

UPDATE TOP(1) Tasks 
    SETState= Processing 
    OUTPUT INSERTED.RetrievedTaskId 
    WHEREState= ReadyForProcessing 

test it out:

DECLARE@Taskstable (RetrievedTaskId  int, State char(1))
INSERT@TasksVALUES (1,'P')
INSERT@TasksVALUES (2,'P')
INSERT@TasksVALUES (3,'R')
INSERT@TasksVALUES (4,'R')

UPDATE TOP (1) @TasksSET State ='P'
  OUTPUT INSERTED.RetrievedTaskId
  WHERE State ='R'SELECT*FROM@Tasks

--OUTPUT:

RetrievedTaskId
---------------
3

(1 row(s) affected)

RetrievedTaskId State
--------------- -----
1               P
2               P
3               P
4               R

(4 row(s) affected)

Solution 3:

I really, really don't like explicit locking in databases, it's a source of all sorts of crazy bugs - and the performance of the database can drop through the floor.

I'd suggest re-writing the SQL along the following lines:

begin transaction;

update tasks
set state = processing
where state = readyForProcessing
and ID = (selectmin(ID) from tasks where state = readyForProcessing);

commit; 

This way, you don't need to lock anything - and because the update is atomic, there's no risk of two processes updating the same record.

Post a Comment for "How Do I Use Locking Hints So That Two Parallel Queries Return Non-intersecting Results?"