sql >> Database >  >> RDS >> PostgreSQL

Adviserende sloten of NOWAIT om wachten op vergrendelde rijen te voorkomen?

FOR UPDATE NOWAIT is alleen een goed idee als u erop staat een bepaalde rij te vergrendelen, wat niet . is wat je nodig hebt. Je wilt gewoon elke kwalificerende, beschikbare (ontgrendelde) rij. Het belangrijke verschil is dit (met verwijzing naar de handleiding voor Postgres 9.4):

Met NOWAIT , meldt de instructie een fout, in plaats van te wachten, als een geselecteerde rij niet onmiddellijk kan worden vergrendeld.

Identieke zoekopdrachten zullen zeer waarschijnlijk dezelfde willekeurige keuze proberen te vergrendelen. FOR UPDATE NOWAIT zal gewoon redden met een uitzondering (die de hele transactie terugdraait, tenzij je de fout opvangt) en je moet het opnieuw proberen.

De oplossing in mijn antwoord waarnaar wordt verwezen op dba.SE gebruikt een combinatie van gewoon FOR UPDATE in combinatie met pg_try_advisory_lock() :

pg_try_advisory_lock lijkt op pg_advisory_lock , behalve dat de functie niet wacht tot het slot beschikbaar is. Het zal het slot onmiddellijk verkrijgen en true retourneren, of false retourneren als het slot niet onmiddellijk kan worden verkregen.

Dus je beste optie is ... het derde alternatief:de nieuwe FOR UPDATE SKIP LOCKED in Postgres 9.5, dat hetzelfde gedrag implementeert zonder extra functieaanroep.

De handleiding voor Postgres 9.5 vergelijkt de twee opties en legt het verschil wat meer uit:

Om te voorkomen dat de bewerking wacht tot andere transacties worden uitgevoerd, gebruikt u de NOWAIT of SKIP LOCKED optie. Met NOWAIT , rapporteert de instructie een fout in plaats van te wachten als een geselecteerde rij niet onmiddellijk kan worden vergrendeld. Met SKIP LOCKED , worden alle geselecteerde rijen die niet onmiddellijk kunnen worden vergrendeld, overgeslagen.

Op Postgres 9.4 of ouder uw volgende beste optie is om pg_try_advisory_xact_lock(id) . te gebruiken in combinatie met FOR UPDATE zoals aangetoond in het antwoord waarnaar wordt verwezen:

  • Postgres-UPDATE ... LIMIET 1

(Ook met een implementatie met FOR UPDATE SKIP LOCKED .)

terzijde

Strikt genomen krijg je willekeurige, niet echt willekeurige keuzes. Dat kan een belangrijk onderscheid zijn.
Een gecontroleerde versie van uw vraag staat in mijn antwoord op uw andere vraag.




  1. Hoe de tijdzone in MySQL te converteren

  2. Databasemail inschakelen in SQL Server (T-SQL)

  3. Hoe te selecteren met behulp van de WITH RECURSIVE-clausule

  4. SQLite Self-Join