е добра идея само ако настоявате да заключите конкретен ред, което е не от какво имаш нужда. Просто искате всякакво квалифициращ, наличен (отключен) ред. Важната разлика е следната (цитирайки ръководството за Postgres 9.4):FOR UPDATE NOWAIT
С
NOWAIT, операторът отчита грешка, вместо да чака, ако избран ред не може да бъде заключен незабавно.
Идентични заявки много вероятно ще се опитат да заключат един и същ произволен избор. FOR UPDATE NOWAIT просто ще се спаси с изключение (което ще върне обратно цялата транзакция, освен ако не хванете грешката) и трябва да опитате отново.
Решението в моя препратен отговор на dba.SE използва комбинация от обикновен FOR UPDATE в комбинация с pg_try_advisory_lock() :
pg_try_advisory_lockе подобен наpg_advisory_lock, освен че функцията няма да чака заключването да стане достъпно. Той или ще получи заключването незабавно и ще върне true, или ще върне false, ако заключването не може да бъде получено незабавно.
Така че вашият най-добрият вариант е ... третата алтернатива:новата FOR UPDATE SKIP LOCKED в Postgres 9.5, който реализира същото поведение без допълнително извикване на функция.
Ръководството за Postgres 9.5 сравнява двете опции, обяснявайки още малко разликата:
За да предотвратите операцията да чака други транзакции за извършване, използвайте или
NOWAITилиSKIP LOCKEDопция. СNOWAIT, операторът отчита грешка, вместо да чака, ако избран ред не може да бъде заключен незабавно. СSKIP LOCKED, всички избрани редове, които не могат да бъдат незабавно заключени, се пропускат.
На Postgres 9.4 или по-стара следващата ви най-добра опция е да използвате pg_try_advisory_xact_lock(id) в комбинация с FOR UPDATE както е показано в посочения отговор:
- Актуализиране на Postgres… ОГРАНИЧЕНИЕ 1
(Също така с реализация с FOR UPDATE SKIP LOCKED .)
Строго погледнато, получавате произволни, а не наистина произволни избори. Това може да е важно разграничение.
Проверена версия на вашата заявка е в моя отговор на другия ви въпрос.