je dobrý nápad pouze tehdy, pokud trváte na uzamčení konkrétního řádku, což není co potřebuješ. Chcete jen jakékoli kvalifikační, dostupný (odemčený) řádek. Důležitý rozdíl je tento (cituji manuál pro Postgres 9.4):FOR UPDATE NOWAIT
Pomocí
NOWAIT
, příkaz namísto čekání hlásí chybu, pokud nelze vybraný řádek okamžitě uzamknout.
Identické dotazy se velmi pravděpodobně pokusí uzamknout stejný libovolný výběr. FOR UPDATE NOWAIT
jen se zachrání s výjimkou (která vrátí celou transakci zpět, pokud chybu nezachytíte) a musíte to zkusit znovu.
Řešení v mé odkazované odpovědi na dba.SE používá kombinaci obyčejného FOR UPDATE
v kombinaci s pg_try_advisory_lock()
:
pg_try_advisory_lock
je podobnýpg_advisory_lock
, kromě toho, že funkce nebude čekat, až bude zámek dostupný. Buď okamžitě získá zámek a vrátí hodnotu true, nebo vrátí hodnotu false, pokud zámek nelze získat okamžitě.
Takže vaše nejlepší možnost je ... třetí alternativa:nový FOR UPDATE SKIP LOCKED
v Postgres 9.5, který implementuje stejné chování bez dalšího volání funkce.
Manuál pro Postgres 9.5 porovnává tyto dvě možnosti a ještě více vysvětluje rozdíl:
Chcete-li zabránit tomu, aby operace čekala na potvrzení jiných transakcí, použijte buď
NOWAIT
neboSKIP LOCKED
volba. PomocíNOWAIT
Pokud nelze vybraný řádek okamžitě uzamknout, příkaz namísto čekání hlásí chybu. SSKIP LOCKED
, všechny vybrané řádky, které nelze okamžitě uzamknout, jsou přeskočeny.
Na Postgres 9.4 nebo starší vaše další nejlepší možnost je použít pg_try_advisory_xact_lock(id)
v kombinaci s FOR UPDATE
jak je ukázáno v odkazované odpovědi:
- AKTUALIZACE Postgresu … LIMIT 1
(Také s implementací s FOR UPDATE SKIP LOCKED
.)
Přísně vzato dostanete svévolné, ne skutečně náhodné výběry. To může být důležitý rozdíl.
Auditovaná verze vašeho dotazu je v mé odpovědi na vaši další otázku.