views:

54

answers:

1

Quite a simple question. In SQL 2008 if I have a stored procedure (see below) do I run the risk of a race condition between the first two statements or does the stored procedure put a lock on the things it touches like transactions do?

ALTER PROCEDURE [dbo].[usp_SetAssignedTo] 
    -- Add the parameters for the stored procedure here
    @Server varchar(50), 
    @User varchar(50),
    @UserPool varchar(50)
AS
BEGIN
    SET NOCOUNT ON;

    -- Find a Free record
    Declare @ServerUser varchar(50)
    (SELECT top 1 @ServerUser = UserName from ServerLoginUsers
    where AssignedTo is null and [TsServer] = @Server)

    --Set the free record to the user
    Update ServerLoginUsers
    set AssignedTo = @User, AssignedToDate = getdate(), SourcePool = @UserPool
    where [TsServer] = @Server and UserName = @ServerUser

    --report record back if it was updated. Null if it was not available.
    select * 
    from ServerLoginUsers 
    where [TsServer] = @Server 
        and UserName = @ServerUser 
        and AssignedTo = @User
END
+3  A: 

You could get a race condition.

It can be done in one statement:

  • You can assign in an UPDATE
  • The lock hints allow another process to skip this row
  • The OUTPUT clause returns data to the caller

Try this... (edit: holdlock removed)

Update TOP (1) ServerLoginUsers WITH (ROWLOCK, READPAST)
OUTPUT INSERTED.*
SET
   AssignedTo = @User, AssignedToDate = getdate(), SourcePool = @UserPool
WHERE
   AssignedTo is null and [TsServer] = @Server   -- not needed -> and UserName = @ServerUser

If not, you may need a separate select

Update TOP (1) ServerLoginUsers WITH (ROWLOCK, READPAST)
SET
    -- yes, assign in an update
   @ServerUser = UserName,
   -- write
   AssignedTo = @User, AssignedToDate = getdate(), SourcePool = @UserPool
OUTPUT INSERTED.*
WHERE
   AssignedTo is null and [TsServer] = @Server   -- not needed -> and UserName = @ServerUser

SELECT ...

See this please for more: http://stackoverflow.com/questions/939831/sql-server-process-queue-race-condition

gbn
output statement needs to be put after the set for the correct syntax
Scott Chamberlain
@gbn I used your first example but I got the error `You can only specify the READPAST lock in the READ COMMITTED or REPEATABLE READ isolation levels.` when I ran it.
Scott Chamberlain
Ah OK, drop thw HOLDLOCK then
gbn
Thanks, that fixed it.
Scott Chamberlain