DEV Community

Freitas-Mp
Freitas-Mp

Posted on

Capítulo 21 — Deadlock: Quando o Sistema Fica Esperando por Ele Mesmo

 Capítulo 21 — Deadlock: Quando o Sistema Fica Esperando por Ele Mesmo

Uma falha que nos obrigou a parar tudo

Estávamos construindo o sistema.

Tudo parecia funcionar.

Até que, durante um teste de concorrência, colocamos cinco execuções fazendo a mesma operação praticamente ao mesmo tempo.

E então apareceu:

ER_LOCK_DEADLOCK

A princípio, parece apenas mais um erro técnico.

Mas a pergunta é muito mais interessante:

«O que significa, de verdade, um sistema entrar em deadlock?»

Foi assim que começou a nossa investigação.


🧑‍💻 Matondo Pedro

João, afinal, o que aconteceu aqui?

👨‍💻 João

Antes de falar de banco de dados, vamos esquecer programação por um momento.

Imagina duas pessoas organizando documentos.

👨 A está segurando um documento que B precisa.

👩 B está segurando outro documento que A precisa.

Então:

👨 A → espera B
👩 B → espera A

Quem continua?

🧑‍💻 Matondo Pedro

Ninguém.

A está esperando B.

B está esperando A.

Então fica tudo travado.

👨‍💻 João

Exatamente.

Agora temos uma descoberta.

Não é simplesmente esperar que causa o problema.

Se B estivesse esperando A, mas A pudesse terminar sozinho:

👩 B → espera 👨 A

👨 A → termina

👩 B → continua

Tudo ficaria bem.

O problema aparece quando a espera volta para o início.

👨 A → espera 👩 B
↑ ↓
└───────┘

Temos um círculo.


🧑‍💻 Matondo Pedro

Então, se tivermos cinco pessoas, pode ficar ainda pior?

👨‍💻 João

Pode.

Imagina:

👨 A espera 👩 B
👩 B espera 👨 C
👨 C espera 👩 D
👩 D espera 👨 E
👨 E espera 👩 A

Agora ninguém consegue avançar.

E olha uma coisa interessante:

nenhuma pessoa necessariamente fez algo errado.

Cada uma simplesmente está esperando outra pessoa.

O problema só aparece quando olhamos para o conjunto inteiro.


Voltando para o nosso sistema

👨‍💻 João

Agora vamos voltar para o S04.

Tínhamos cinco execuções acontecendo simultaneamente:

Execução A ─┐
Execução B ─┤
Execução C ─┼──→ mesma interactionId
Execução D ─┤
Execução E ─┘

O cursor daquela interação ainda não existia.

Então todas chegaram praticamente à mesma conclusão:

«"Não existe cursor. Preciso criá-lo."»

E todas tentaram fazer isso.

Foi aí que apareceu o nosso:

ER_LOCK_DEADLOCK

🧑‍💻 Matondo Pedro

Ah! Então o problema que encontramos no nosso projeto é o mesmo padrão.

👨‍💻 João

Exatamente.

Mas com uma precisão importante:

não significa que o banco de dados inteiro parou.

Algumas operações ficaram envolvidas numa dependência circular.

O banco detectou a situação e escolheu uma ou mais transações como vítimas, desfazendo aquela operação para permitir que o sistema continuasse.


🧑‍💻 Matondo Pedro

Então o banco precisa "matar" alguns processos?

👨‍💻 João

De forma simplificada, podemos dizer isso.

Tecnicamente, ele pode abortar uma transação e fazer rollback.

E isso produz uma descoberta interessante:

«Às vezes, o erro é justamente o mecanismo que impede o sistema de ficar bloqueado para sempre.»


Mas isso só acontece em bancos de dados?

🧑‍💻 Matondo Pedro

Essa é uma coisa que fiquei curioso.

Deadlock só acontece em banco de dados?

👨‍💻 João

Não.

O banco é apenas um dos lugares onde esse problema aparece.

O padrão é muito mais amplo.

Pode acontecer quando:

  • 👥 pessoas esperam umas pelas outras;
  • 🏭 máquinas dependem umas das outras;
  • 🚗 veículos ficam presos em uma passagem;
  • 💻 programas aguardam recursos;
  • 🗄️ transações aguardam recursos do banco.

A estrutura é sempre parecida:

A possui X
A precisa de Y

B possui Y
B precisa de X

E então:

A → espera B
↑ ↓
└───────┘


🧑‍💻 Matondo Pedro

Então, quando estamos projetando um sistema, precisamos levantar essas situações e tentar prever esses problemas?

👨‍💻 João

Sim.

Não conseguimos prever todos os problemas antes de construir um sistema.

Mas podemos investigar:

O que é compartilhado?

Quem pode utilizar?

Quem pode precisar esperar?

Enquanto espera, o que continua segurando?

Existe possibilidade de formar um ciclo?

Essa análise pode revelar riscos de concorrência antes que eles apareçam em produção.


Uma pequena experiência

👨‍💻 João

Agora olha para duas situações.

Primeira:

👨 A → X → Y
👩 B → Y → X

Existe possibilidade de formar um ciclo.

Agora mudamos a ordem:

👨 A → X → Y
👩 B → X → Y

O que acontece?

🧑‍💻 Matondo Pedro

Aí não temos círculo.

B pode esperar A.

Mas A não está esperando B.

Quando A terminar, B continua.

Então não temos deadlock.

👨‍💻 João

Exatamente.

Acabaste de descobrir uma das estratégias fundamentais para reduzir deadlocks:

«estabelecer uma ordem consistente para adquirir recursos.»


E se o banco não detectasse?

🧑‍💻 Matondo Pedro

Mas o que aconteceria se o banco nunca detectasse aquele deadlock?

👨‍💻 João

Imagina:

A ⏳
B ⏳

Se nenhuma pudesse sair da situação, poderiam ficar esperando indefinidamente.

E outras operações poderiam começar a esperar também:

A ⏳
B ⏳
C ⏳
D ⏳
E ⏳
...

Isso poderia consumir conexões e outros recursos, aumentar os tempos de resposta, provocar timeouts e degradar o sistema.

O sistema estaria gastando recursos sem produzir progresso útil.


🧑‍💻 Matondo Pedro

Agora lembrei de uma coisa!

Na 42 Luanda estudamos um problema chamado Dining Philosophers — O Jantar dos Filósofos.

👨‍💻 João

E agora a conexão fica muito interessante.

Nós não começamos pelos filósofos.

Encontramos o problema primeiro no nosso sistema.

Depois percebemos que existia um problema clássico que representa exatamente essa classe de situação.

🍝 Dining Philosophers Nosso sistema

🧑 Filósofo Execução
🍴 Garfo Recurso
⏳ Espera Espera
🔄 Ciclo Dependência circular
🔒 Bloqueio Deadlock

E essa é talvez a parte mais interessante da investigação.

Não estudamos deadlock porque alguém começou dizendo:

«"Deadlock é X."»

Nós começamos com:

«"Por que o nosso sistema travou?"»

Investigamos.

Fizemos perguntas.

Criamos hipóteses.

Simplificamos o problema.

Encontramos o padrão.

E só depois demos nome ao que havíamos descoberto:

«Deadlock.»

Esse é o espírito do Adaptive Inquiry: começar pelo problema real, investigar através de perguntas, descobrir o conceito e só então aprender o termo técnico.

A teoria veio depois da necessidade de entendê-la.

Top comments (0)