er kun en god idé, hvis du insisterer på at låse en bestemt række, hvilket ikke er hvad du har brug for. Du vil bare have hvilket som helst kvalificerende, tilgængelig (ulåst) række. Den vigtige forskel er denne (med henvisning til manualen til Postgres 9.4):FOR UPDATE NOWAIT
Med NOWAIT
, rapporterer erklæringen en fejl i stedet for at vente, hvis en valgt række ikke kan låses med det samme.
Identiske forespørgsler vil højst sandsynligt forsøge at låse det samme vilkårlige valg. FOR UPDATE NOWAIT
vil bare redde ud med en undtagelse (som vil rulle hele transaktionen tilbage, medmindre du fanger fejlen), og du skal prøve igen.
Løsningen i mit refererede svar på dba.SE bruger en kombination af almindelig FOR UPDATE
i kombination med pg_try_advisory_lock()
:
pg_try_advisory_lock
ligner pg_advisory_lock
, bortset fra at funktionen ikke venter på, at låsen bliver tilgængelig. Den vil enten få låsen med det samme og returnere sand, eller returnere falsk, hvis låsen ikke kan erhverves med det samme.
Så din bedste mulighed er ... det tredje alternativ:det nye FOR UPDATE SKIP LOCKED
i Postgres 9.5, som implementerer den samme adfærd uden yderligere funktionskald.
Manualen til Postgres 9.5 sammenligner de to muligheder og forklarer forskellen lidt mere:
For at forhindre operationen i at vente på, at andre transaktioner udføres, skal du bruge enten NOWAIT
eller SKIP LOCKED
mulighed. Med NOWAIT
, rapporterer erklæringen en fejl i stedet for at vente, hvis en valgt række ikke kan låses med det samme. Med SKIP LOCKED
, springes alle valgte rækker, der ikke umiddelbart kan låses over.
På Postgres 9.4 eller ældre er din næstbedste mulighed er at bruge pg_try_advisory_xact_lock(id)
i kombination med FOR UPDATE
som vist i det refererede svar:
- Postgres OPDATERING … GRÆNSE 1
(Også med en implementering med FOR UPDATE SKIP LOCKED
.)
Strengt taget får du vilkårlige, ikke virkelig tilfældige valg. Det kan være en vigtig sondring.
En revideret version af din forespørgsel er i mit svar på dit andet spørgsmål.