är bara en bra idé om du insisterar på att låsa en viss rad, vilket är inte vad du behöver. Du vill bara ha vilken som helst kvalificerande, tillgänglig (olåst) rad. Den viktiga skillnaden är denna (med hänvisning till manualen för Postgres 9.4):FOR UPDATE NOWAIT
Med
NOWAIT
, rapporterar uttalandet ett fel, snarare än att vänta, om en vald rad inte kan låsas omedelbart.
Identiska frågor kommer med stor sannolikhet att försöka låsa samma godtyckliga val. FOR UPDATE NOWAIT
kommer bara att lösas ut med ett undantag (vilket kommer att återställa hela transaktionen om du inte fäller felet) och du måste försöka igen.
Lösningen i mitt refererade svar på dba.SE använder en kombination av vanlig FOR UPDATE
i kombination med pg_try_advisory_lock()
:
pg_try_advisory_lock
liknarpg_advisory_lock
, förutom att funktionen inte väntar på att låset blir tillgängligt. Det kommer antingen att få låset omedelbart och returnera sant, eller returnera falskt om låset inte kan erhållas omedelbart.
Så ditt bästa alternativ är ... det tredje alternativet:det nya FOR UPDATE SKIP LOCKED
i Postgres 9.5, som implementerar samma beteende utan ytterligare funktionsanrop.
Manualen för Postgres 9.5 jämför de två alternativen och förklarar skillnaden lite mer:
För att förhindra att operationen väntar på att andra transaktioner genomförs, använd antingen
NOWAIT
ellerSKIP LOCKED
alternativ. MedNOWAIT
, rapporterar uttalandet ett fel, snarare än att vänta, om en vald rad inte kan låsas omedelbart. MedSKIP LOCKED
, alla markerade rader som inte kan låsas omedelbart hoppas över.
På Postgres 9.4 eller äldre är ditt näst bästa alternativ är att använda pg_try_advisory_xact_lock(id)
i kombination med FOR UPDATE
som visas i det refererade svaret:
- Postgres UPPDATERING … GRÄNS 1
(Även med en implementering med FOR UPDATE SKIP LOCKED
.)
Strängt taget får du godtyckliga, inte riktigt slumpmässiga val. Det kan vara en viktig skillnad.
En granskad version av din fråga finns i mitt svar på din andra fråga.