01
O que é um deadlock e o que o banco faz quando encontra um
Um deadlock é uma espera circular: a transação A segura um lock que B precisa e B segura um lock que A precisa. Nenhuma das duas pode avançar, e esperar mais não resolve nada. Não é lentidão nem falta de recurso, é um impasse lógico entre transações que fazem exatamente o que deveriam fazer. Por isso ele não aparece em teste unitário, em ambiente de desenvolvimento nem com tráfego baixo: depende de duas transações sobrepostas no tempo, tocando as mesmas linhas em ordens diferentes.
Tempo Transacao A (Ana paga Bia) Transacao B (Bia paga Ana)
t1 UPDATE contas ... WHERE id = 1
(trava a linha da Ana)
t2 UPDATE contas ... WHERE id = 2
(trava a linha da Bia)
t3 UPDATE contas ... WHERE id = 2
(espera B soltar a linha da Bia)
t4 UPDATE contas ... WHERE id = 1
(espera A soltar a linha da Ana)
t5 Ninguem avanca: A espera B e B espera A.
Apos deadlock_timeout (1s) o Postgres aborta uma delas:
ERROR: deadlock detected (SQLSTATE 40P01)
A outra transacao termina normalmente.O PostgreSQL não impede o deadlock, ele o detecta. Quando uma transação espera um lock por mais de deadlock_timeout, que por padrão é 1 segundo, o banco percorre o grafo de quem espera quem. Se encontra um ciclo, aborta uma das transações do ciclo com o erro 40P01 e deixa as outras seguirem. Duas consequências práticas: o usuário da transação escolhida como vítima espera pelo menos um segundo antes de receber o erro, e a transação vítima desfaz todo o trabalho já feito, inclusive o que não tinha relação com o conflito. O MySQL com InnoDB faz o equivalente, detecta o ciclo e devolve o erro 1213, e o SQL Server escolhe uma vítima e devolve o erro 1205.
| O que você observa | O que está acontecendo | Onde olhar |
|---|---|---|
| ERROR: deadlock detected, SQLSTATE 40P01 | Ciclo de espera detectado, esta transação foi a vítima | Log do banco, que lista os processos, as consultas e os locks envolvidos |
| Requisições que demoram exatamente 1 segundo a mais e depois falham | A vítima esperou deadlock_timeout antes de ser abortada | Latência p99 com degraus em torno de 1 s |
| Requisições lentas sem erro e sem ciclo | Espera longa por lock, não deadlock: alguém segura a linha por tempo demais | pg_blocking_pids e idade da transação |
| Falha só em horário de pico ou em job em lote | A janela de sobreposição só fica grande com carga ou com lote | Correlacionar os erros com a agenda dos jobs |