FOR UPDATE NOWAIT
ComNOWAIT
, a instrução relatará um erro, em vez de aguardar, se uma linha selecionada não puder ser bloqueada imediatamente.
Consultas idênticas provavelmente tentarão bloquear a mesma escolha arbitrária.
FOR UPDATE NOWAIT
apenas sairá com uma exceção (que reverterá toda a transação, a menos que você intercepte o erro) e você terá que tentar novamente. A solução na minha resposta referenciada no dba.SE usa uma combinação de
FOR UPDATE
simples em combinação com pg_try_advisory_lock()
:
pg_try_advisory_lock
é semelhante apg_advisory_lock
, exceto que a função não aguardará a disponibilização do bloqueio. Ele obterá o bloqueio imediatamente e retornará verdadeiro, ou retornará falso se o bloqueio não puder ser adquirido imediatamente.
Portanto, sua melhor opção é ... a terceira alternativa:o novo
FOR UPDATE SKIP LOCKED
no Postgres 9.5, que implementa o mesmo comportamento sem chamada de função adicional. O manual do Postgres 9.5 compara as duas opções, explicando um pouco mais a diferença:
Para evitar que a operação aguarde a confirmação de outras transações, use o comandoNOWAIT
ouSKIP LOCKED
opção. ComNOWAIT
, a instrução relatará um erro, em vez de aguardar, se uma linha selecionada não puder ser bloqueada imediatamente. ComSKIP LOCKED
, todas as linhas selecionadas que não puderem ser bloqueadas imediatamente serão ignoradas.
No Postgres 9.4 ou anterior, sua próxima melhor opção é usar
pg_try_advisory_xact_lock(id)
em combinação com FOR UPDATE
como demonstrado na resposta referenciada:- Atualização do Postgres … LIMITE 1
(Também com uma implementação com
FOR UPDATE SKIP LOCKED
.) Aparte
Estritamente falando, você obtém escolhas arbitrárias, não verdadeiramente aleatórias. Essa pode ser uma distinção importante.
Uma versão auditada de sua consulta está na minha resposta à sua outra pergunta.