2009-06-02 8 views
36

Ho una coda ordini a cui si accede da più processori di ordini tramite una stored procedure. Ogni processore passa in un ID univoco che viene utilizzato per bloccare i prossimi 20 ordini per il proprio uso. La stored procedure restituisce quindi questi record al processore degli ordini su cui agire.Condizione processo coda server SQL

ci sono casi in cui più processori sono in grado di richiamare l'annotazione stesso 'OrderTable' al punto che cercano di operare contemporaneamente su di esso. Questo alla fine si traduce in errori lanciati più avanti nel processo.

mio prossimo corso di azione è quello di consentire ad ogni afferrare processore tutti gli ordini disponibili e Robin proprio dietro i processori ma speravo di fare semplicemente questa sezione del codice thread-safe e consentire i processori per afferrare record ogni volta che vogliono.

Così esplicitamente - Qualche idea del perché sto vivendo questa condizione di gara e di come posso risolvere il problema.

BEGIN TRAN 
    UPDATE OrderTable WITH (ROWLOCK) 
    SET  ProcessorID = @PROCID 
    WHERE OrderID IN (SELECT TOP (20) 
             OrderID 
           FROM OrderTable WITH (ROWLOCK) 
           WHERE ProcessorID = 0) 
COMMIT TRAN 


SELECT OrderID, ProcessorID, etc... 
FROM OrderTable 
WHERE ProcessorID = @PROCID 
+4

@Keltex: Ovviamente lui vuole sapere come riscrivere questa procedura memorizzata in modo che non risulti in due processori che elaborano lo stesso (i) record. – Welbog

risposta

48

Edit:

Ho cercato su google per controllare la mia risposta: "Processing Data Queues in SQL Server with READPAST and UPDLOCK". Sono passati anni da quando ho letto e giocato con questa soluzione.

originale:

Se si utilizza l'hint READPAST, filari poi bloccati vengono saltati. Hai usato ROWLOCK in modo da evitare l'escalation dei blocchi. Hai anche bisogno di UPDLOCK, come ho scoperto.

Così Processo 1 serrature 20 righe, processo 2 avrà successivo 20, processo 3 richiede righe 41 60, ecc

L'aggiornamento può anche essere scritta così:

UPDATE TOP (20) 
    foo 
SET 
    ProcessorID = @PROCID 
FROM 
    OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK) 
WHERE 
    ProcessorID = 0 

Refresh, Ott 2011

Questo può essere fatto in modo più elegante con la clausola OUTPUT se è necessario un SELEZIONA e un AGGIORNAMENTO in un colpo solo.

+0

Interessante ... Darò questo un tentativo –

+0

L'aggiunta di ulteriori suggerimenti mi è stata di grande aiuto. Niente più duplicati. Grazie. –

+0

So che questo è vecchio, ma l'hint 'UPDLOCK' nell'istruzione' UPDATE' costringe i blocchi degli aggiornamenti (invece dei blocchi condivisi) mentre * legge * le righe da aggiornare? In altre parole, se non si utilizza 'UPDLOCK', è possibile che esista una condizione di competizione e due istruzioni di aggiornamento per selezionare le stesse righe? –