8

Una domanda semplice. In SQL 2008 se ho una procedura memorizzata (vedi sotto) corro il rischio di una condizione di competizione tra le prime due dichiarazioni o la procedura memorizzata mette un blocco sulle cose che tocca come fanno le transazioni?Le stored procedure bloccano tabelle/righe?

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 

risposta

3

È possibile ottenere una condizione di gara.

Può essere fatto in una sola dichiarazione:

  • È possibile assegnare in un UPDATE
  • I suggerimenti di blocco permettono un altro processo per saltare questa riga
  • clausola OUTPUT restituisce i dati al chiamante

Prova questo ... (edit: HOLDLOCK rimosso)

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 

In caso contrario, potrebbe essere necessario un separato selezionare

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

Vai a questa si prega di più: SQL Server Process Queue Race Condition

+0

dichiarazione di uscita deve essere messo dopo il set per la sintassi corretta –

+0

Ho usato il vostro primo esempio ma ho ricevuto l'errore 'È possibile specificare il blocco READPAST solo nei livelli di isolamento READ COMMITTED o REPEATABLE READ. quando l'ho eseguito. –

+0

Ah OK, rilasciatelo HOLDLOCK quindi – gbn