Locks e Deadlocks em Bancos de Dados: Guia definitivo

março 5, 2024 | por dbsnoop

o guia definitivo de locks e deadlocks para bancos relacionais

Para um DevOps ou DBA que gerencia ambientes de missão crítica, poucos problemas são tão pungentes e mal compreendidos quanto a contenção de locks e os deadlocks. São elementos sutis que transformam uma infraestrutura robusta em um sistema lento, geram timeouts inexplicáveis e, no pior cenário, derrubam aplicações inteiras durante a Black Friday.

Alguns profissionais lidam com locks como se fossem uma lentidão qualquer, ou tratam deadlocks como erros aleatórios do banco que se resolvem com um simples retry na aplicação. Isso mostra-se como uma abordagem perigosa, pois locks não são um problema simples de hardware, pelo contrário: são um problema de concorrência, design e engenharia do seu ambiente de dados.

Neste guia definitivo, consolidamos todo o conhecimento necessário para você dominar o assunto: da teoria mecânica dos bancos de dados relacionais até queries prontas para diagnóstico e estratégias avançadas de resolução.

1. O Que São Locks e Por Que Eles Existem?

Antes de demonizar o lock, é preciso entender que ele faz parte do jogo. Locks (bloqueios) são mecanismos inerentes e essenciais em qualquer SGBD (Sistema Gerenciador de Banco de Dados) relacional para garantir a integridade dos dados e as propriedades ACID (Atomicidade, Consistência, Isolamento e Durabilidade).

Para compreender melhor, pense em um sistema bancário: dois usuários tentam sacar dinheiro da mesma conta ao mesmo tempo. Como garantir que não saquem quantias duplicadas e deixem o saldo negativo? Para isso, o banco de dados “tranca” (lock) o registro da conta para o primeiro usuário, o que obriga o segundo a esperar, e só libera após a conclusão da transação.

Os Tipos de Locks Essenciais

Embora cada banco (Oracle, SQL Server, PostgreSQL) tenha nomenclaturas próprias, os conceitos universais são:

  1. Locks de Leitura (Shared Locks – S): Permitem que múltiplos usuários leiam o dado simultaneamente (concorrência de leitura), mas impedem que qualquer transação modifique aquele dado enquanto a leitura ocorre.
  2. Locks de Escrita (Exclusive Locks – X): O bloqueio total. Se uma transação segura um lock exclusivo para fazer um UPDATE ou DELETE, ninguém mais lê e ninguém mais escreve naquele recurso até que o lock seja liberado (COMMIT ou ROLLBACK).
  3. Locks de Atualização (Update Locks – U): Um estado híbrido usado para prevenir deadlocks. A transação sinaliza que vai modificar o dado, mas ainda está na fase de leitura. Isso evita que múltiplas sessões tentem escalar de leitura para escrita ao mesmo tempo.
  4. Locks de Intenção (Intent Locks): Uma sinalização hierárquica. O banco avisa: “Vou bloquear uma linha lá dentro desta tabela, então não tente bloquear a tabela inteira agora”.

Quando a Fila Para (Blocking)

Portanto, sabemos que o problema não é a existência do lock, mas na verdade a sua duração e a sua granularidade. O lock se torna um problema de performance quando:

  • Concorrência Excessiva: Centenas de sessões tentando acessar a mesma tabela ou registro simultaneamente.
  • Transações Longas: Um UPDATE que demora 30 segundos segura o recurso por 30 segundos. Todo o resto do sistema para e entra em fila de espera (Wait Events).
  • Granularidade Inadequada: O banco decide bloquear a tabela inteira (Table Lock) para atualizar apenas algumas linhas, paralisando a operação de todos os usuários.

2. O Deadlock

Enquanto o Lock pode ser considerado uma fila, o Deadlock é um conjestionamento travado no qual nada se move.

Um deadlock ocorre quando duas ou mais sessões entram em um ciclo de dependência mútua, conhecido como Espera Circular.

  • Sessão A tem a chave do Recurso 1 e quer acessar o Recurso 2.
  • Sessão B tem a chave do Recurso 2 e quer acessar o Recurso 1.

Nenhuma passagem é concedida e ninguém avança. O banco de dados detecta esse ciclo matematicamente impossível de resolver e intervém drasticamente: mata uma das sessões para permitir que a outra siga em frente. Para a plicação, isso gera um output de erro fatal, como o 1205 no SQL Server.

As 4 Condições Matemáticas do Deadlock (Condições de Coffman)

Para que um deadlock ocorra, quatro condições precisam ser verdadeiras simultaneamente. Se você quebrar uma delas através de design ou código, o deadlock desaparece:

  1. Exclusão Mútua: O recurso só aceita um dono por vez (Write Locks).
  2. Posse e Espera (Hold and Wait): Eu seguro um recurso enquanto espero por outro.
  3. Não Preempção: O banco não pode arrancar o lock da sua mão à força (exceto matando a sessão).
  4. Espera Circular: A cadeia fecha em si mesma (A espera B, que espera A).

3. Diagnóstico Prático: Como Detectar Locks?

Uma operação que atinge consistentemente seu SLA não pode esperar a reclamação do usuário, é necessário ter visibilidade em tempo real. Abaixo estão as queries essenciais para identificar quem está travando quem.

1. SQL Server (DMVs)

Esta query identifica bloqueios ativos em tempo real:

SELECT 
    blocking_session_id AS Blocker_Session,
    session_id AS Victim_Session,
    wait_type,
    wait_time AS Wait_Time_MS,
    last_wait_type,
    TEXT AS Query_Text
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
WHERE blocking_session_id <> 0;

2. Oracle Database

Para identificar a cadeia de bloqueio no Oracle:

SELECT 
    s1.username || '@' || s1.machine || ' (SID=' || s1.sid || ' ) is blocking '
    || s2.username || '@' || s2.machine || ' (SID=' || s2.sid || ' ) ' AS blocking_status
FROM v$lock l1, v$session s1, v$lock l2, v$session s2
WHERE s1.sid=l1.sid AND s2.sid=l2.sid
AND l1.BLOCK=1 AND l2.request > 0
AND l1.id1 = l2.id1 AND l2.id2 = l2.id2;

3. PostgreSQL

Para ver quem está bloqueando quem no Postgres:

SELECT 
    blocked_locks.pid     AS blocked_pid,
    blocked_activity.usename  AS blocked_user,
    blocking_locks.pid     AS blocking_pid,
    blocking_activity.usename AS blocking_user,
    blocked_activity.query    AS blocked_statement,
    blocking_activity.query   AS current_statement_in_blocking_process
FROM  pg_catalog.pg_locks         blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks         blocking_locks 
    ON blocking_locks.locktype = blocked_locks.locktype
    AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
    AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
    AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
    AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
WHERE NOT blocked_locks.granted;

4. Estratégias Definitivas para Eliminar e Prevenir Locks

Para sanar o problema na raiz, precisamos atuar em quatro frentes: SQL, Modelagem, Aplicação e Infraestrutura.

a. Otimização de Queries e Índices (A Causa #1)

Uma query rápida segura locks por menos tempo.

Se um UPDATE precisa varrer a tabela inteira (Table Scan) para encontrar o registro a ser alterado, ele pode bloquear a tabela inteira no processo.

  • A Solução: Crie índices que suportem as cláusulas WHERE e JOIN. Se o banco encontrar o registro instantaneamente (Index Seek), o lock será aplicado apenas naquela linha (Row Lock), liberando o resto da tabela para outros usuários.

b. Transações Curtas e Atômicas

O erro mais comum de desenvolvedores é abrir uma transação (BEGIN TRAN), fazer um update, e depois realizar chamadas de API externas, envio de e-mails ou processamento complexo em memória antes do COMMIT.

  • A Solução: Mantenha a transação o mais curta possível. Prepare os dados antes de abrir a transação. Faça o Update. Dê o Commit. Só depois envie o e-mail ou chame a API.

c. Padronização da Ordem de Acesso (Fim dos Deadlocks)

Lembre-se da “Espera Circular”. Se a Aplicação X acessa a Tabela A e depois a B, e a Aplicação Y acessa a Tabela B e depois a A, um deadlock certamente irá ocorrer.

  • A Solução: Crie uma convenção rigorosa de codificação. “Sempre acessamos tabelas em ordem alfabética” ou “Sempre atualizamos Mestre antes de Detalhe”. Se todos seguem o mesmo fluxo, o ciclo não se fecha.

d. Hardware e Configuração de Disco

A razão para um lock demorado também pode ser o seu disco lento. Se o banco de dados sofre para gravar o log de transação em um disco HDD velho ou saturado, o lock fircará ativo esperando o I/O de dsico completar.

e. Níveis de Isolamento (RCSI no SQL Server)

Muitos bloqueios ocorrem entre quem lê (SELECT) e quem escreve (UPDATE).

  • A Solução: Em bancos como SQL Server, habilitar o RCSI (Read Committed Snapshot Isolation) faz com que leitores usem versionamento de linha (no TempDB) em vez de locks. Isso significa que quem lê não bloqueia quem escreve, e quem escreve não bloqueia quem lê.

5. Estudo de Caso Real: ERP de Varejo

Vamos analisar um caso de uso do dbsnOOp durante uma Black Friday:

Um grande ERP de varejo estava processando milhares de pedidos por minuto. CPU e Memória estavam sobrando (abaixo de 40%), mas o sistema estava lento, com clientes recebendo erros de timeout no checkout. Ao utilizar a observabilidade profundo e movida por IA do dbsnOOp, não se olha apenas para a CPU: é possível ir direto à análise de espera (Wait Statistics).

Foi odentificada uma cadeia massiva de locks. A causa raiz não era o volume de vendas, mas um Job de atualização de estoque que rodava a cada 5 minutos.

  1. O Job abria uma transação gigante para atualizar 5.000 produtos de uma vez.
  2. Enquanto ele rodava (durava 45 segundos), bloqueava a tabela de produtos.
  3. Os clientes tentando comprar (fazer SELECT e UPDATE no estoque) ficavam em fila esperando o Job terminar.
  4. O acúmulo de conexões esperando estourava o pool de conexões da aplicação, gerando o erro de timeout.

Solução (Mitigação em 15 minutos):

Com a identificação precisa da query bloqueadora (o Job) e das vítimas (o Checkout), a equipe atuou:

  1. Imediato: O Job foi pausado durante o horário de pico.
  2. Definitivo: O Job foi refatorado para atualizar em lotes pequenos (batching) de 100 produtos por vez, com COMMIT a cada lote. Isso permitiu que as vendas “entrassem” nos intervalos dos lotes, eliminando a percepção de travamento.

Resultado: O tempo de resposta do checkout caiu de 8 segundos (com timeouts) para 200ms.

6: Por Que o Monitoramento Tradicional Falha com Locks?

Ferramentas mais rudimentares de monitoramento de infraestrutura (Zabbix, Nagios, CloudWatch) olham somente para recursos (CPU, RAM, Disco). Contudo, locks não consumem recursos diretamente, locks consomem tempo.

Se o seu banco de dados está travado por um deadlock, o uso de CPU pode cair para 1%, porque ninguém consegue fazer nada. O monitoramento tradicional dirá que o servidor está “saudável” e “ocioso”, enquanto seu telefone não para de tocar com usuários reclamando.

Como o dbsnOOp Resolve Isso

A plataforma dbsnOOp foi desenhada especificamente para a profundidade dos bancos de dados.

  1. Histórico de Deadlocks: Não apenas alertamos, mas guardamos o grafo do deadlock. Você pode voltar no tempo e ver exatamente qual query entrou em conflito com qual ontem à noite às 03:00h.
  2. Correlação com Deploy: Cruzamos dados de performance com alterações recentes. Se os locks começaram após o último deploy, você sabe onde procurar.
  3. IA e Query Performance: Nossa IA analisa os padrões de espera e sugere índices ou refatorações de query automaticamente para prevenir a recorrência.

Em suma, sabemos que locks não são fatalidades, mas sinais de que seu ambiente de Banco de Dados precisa de ajustes. Nesse contexto, mostra-se essencial que sejam feitas as devidas otimizações para que sua equipe não fique presa de lock em lock.

A diferença entre um sistema que trava e um que escala é a Observabilidade. Você não pode consertar o que não vê. Se você quer parar de adivinhar por que o banco está lento e começar a ver a causa raiz em segundos, é hora de evoluir seu monitoramento.

Agende uma demonstração aqui

Saiba mais sobre o dbsnOOp!

Visite nosso canal no youtube e aprenda sobre a plataforma e veja tutoriais

Aprenda sobre monitoramento de banco de dados com ferramentas avançadas aqui.

Leitura Recomendada

  • Por que confiar só no monitoramento é arriscado sem um assessment técnico: Explore a diferença crítica entre o monitoramento passivo, que apenas observa sintomas, e um assessment técnico profundo, que investiga a causa raiz dos problemas. O texto aborda os riscos de operar com uma falsa sensação de segurança baseada apenas em dashboards de monitoria.
  • Seu banco de dados pode estar doente (e você nem percebeu): Descubra os sinais de problemas crônicos e silenciosos que não disparam alertas óbvios, mas que degradam a performance e a estabilidade ao longo do tempo. O artigo foca na necessidade de diagnósticos que vão além das métricas superficiais para encontrar a verdadeira saúde do seu ambiente de dados.
  • Performance Tuning: como aumentar velocidade sem gastar mais hardware: Antes de aprovar o upgrade de uma instância, é fundamental esgotar as otimizações de software. Este guia foca em técnicas de performance tuning que permitem extrair o máximo de desempenho do seu ambiente atual, resolvendo a causa raiz da lentidão em queries e índices, em vez de apenas remediar os sintomas com hardware mais caro.
Compartilhar:

Leia mais

IMPULSIONE SUA OPERAÇÃO COM UM DBA AUTÔNOMO

SEM INSTALAÇÃO – 100% SAAS 

Complete o formulário abaixo para prosseguir

*Obrigatórias