PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Bloqueios consultivos ou NOWAIT para evitar esperar por linhas bloqueadas?


FOR UPDATE NOWAIT é apenas uma boa ideia se você insistir em bloquear uma linha específica, o que não o que você precisa. Você só quer qualquer linha de qualificação, disponível (desbloqueada). A diferença importante é esta (citando o manual do Postgres 9.4):

Com NOWAIT , 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 a pg_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 comando NOWAIT ou SKIP LOCKED opção. Com NOWAIT , a instrução relatará um erro, em vez de aguardar, se uma linha selecionada não puder ser bloqueada imediatamente. Com SKIP 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.