8

很简单的问题。在SQL 2008中,如果我有一个存储过程(请参阅下文),是否存在前两条语句之间存在争用条件的风险,或者存储过程是否像事务一样对它所触及的事件进行锁定?存储过程是否锁定表/行?

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; 
    Declare @ServerUser varchar(50) 

    -- Find a Free record 
    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

您可能会遇到竞争状况。

它可以在一个语句来完成:

  • 您可以在UPDATE
  • 的锁提示允许指定另一个进程跳过此行
  • OUTPUT子句将数据返回给调用者

尝试......(编辑:HOLDLOCK删除)

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 

如果没有,你可能需要一个单独的选择

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 ... 

此,请为查看更多:SQL Server Process Queue Race Condition

+0

输出语句需要设定之后要放在正确的语法 – 2010-10-01 18:10:01

+0

我用你的第一个例子但是我得到了错误:'当我运行它时,你只能在READ COMMITTED或REPEATABLE READ隔离级别指定READPAST锁。 – 2010-10-01 18:14:29

+0

啊好的,放下这个HOLDLOCK,然后 – gbn 2010-10-01 18:19:17