PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Blocchi di avviso o NOWAIT per evitare di aspettare le righe bloccate?

FOR UPDATE NOWAIT è una buona idea solo se insisti nel bloccare una riga particolare, che è non quello di cui hai bisogno. Vuoi solo qualsiasi qualificazione, riga disponibile (sbloccata). La differenza importante è questa (citando il manuale di Postgres 9.4):

Con NOWAIT , l'istruzione segnala un errore, anziché attendere, se una riga selezionata non può essere bloccata immediatamente.

Query identiche cercheranno molto probabilmente di bloccare la stessa scelta arbitraria. FOR UPDATE NOWAIT eseguirà il salvataggio con un'eccezione (che annullerà l'intera transazione a meno che tu non intercetta l'errore) e devi riprovare.

La soluzione nella mia risposta di riferimento su dba.SE utilizza una combinazione di semplice FOR UPDATE in combinazione con pg_try_advisory_lock() :

pg_try_advisory_lock è simile a pg_advisory_lock , tranne che la funzione non attenderà che il blocco diventi disponibile. Otterrà il blocco immediatamente e restituirà true, oppure restituirà false se il blocco non può essere acquisito immediatamente.

Quindi la tua opzione migliore è... la terza alternativa:il nuovo FOR UPDATE SKIP LOCKED in Postgres 9.5, che implementa lo stesso comportamento senza chiamata di funzione aggiuntiva.

Il manuale di Postgres 9.5 confronta le due opzioni, spiegando un po' di più la differenza:

Per evitare che l'operazione attenda il commit di altre transazioni, utilizzare il NOWAIT o SKIP LOCKED opzione. Con NOWAIT , l'istruzione segnala un errore, anziché attendere, se una riga selezionata non può essere bloccata immediatamente. Con SKIP LOCKED , tutte le righe selezionate che non possono essere bloccate immediatamente vengono saltate.

Su Postgres 9.4 o versioni precedenti la tua opzione migliore consiste nell'usare pg_try_advisory_xact_lock(id) in combinazione con FOR UPDATE come dimostrato nella risposta di riferimento:

  • AGGIORNAMENTO Postgres... LIMITE 1

(Anche con un'implementazione con FOR UPDATE SKIP LOCKED .)

A parte

A rigor di termini si ottengono scelte arbitrarie, non veramente casuali. Questa può essere una distinzione importante.
Una versione controllata della tua domanda è nella mia risposta all'altra tua domanda.