Desvendando Deadlocks SQL

5 min de leitura

Desvendando deadlocks SQL — Consultoria

Introdução

O cliente era uma grande empresa de transportes. Esta consultoria tinha o objetivo de resolver deadlocks intermitentes em um SQL Server 2008. Quando esses deadlocks ocorriam em transações, dinheiro, imagem da empresa e tempo dos funcionários eram perdidos.

O Briefing

A aplicação que manipulava esse banco de dados era escrita em VB.net rodando como COM+. Sim, COM+, eu também não sabia o que era isso — é uma tecnologia para executar sua aplicação como componentes de software introduzida pela Microsoft em 1993.

A empresa ficava em uma cidade próxima a São Paulo — Brasil, então tomei o ônibus de manhã cedo e fui lá. No meu primeiro dia na empresa, meu conhecimento sobre deadlocks era muito básico. Eu sabia o conceito, mas não tinha ideia dos detalhes de bloqueio do motor de banco de dados.

Investigação Inicial

Comecei perguntando aos desenvolvedores o que eles achavam que poderia ser a causa dos deadlocks e obtive: “É culpa do banco de dados”. E você pode imaginar que a resposta dos DBAs era simples: “É culpa da aplicação”.

Duas pessoas apontando uma para a outra

O DBA me mostrou as sessões existentes do SQL Profiler de momentos em que os deadlocks ocorreram. Havia queries normais, mas não havia nada muito óbvio sobre o porquê dos deadlocks estarem ocorrendo.

Minha primeira rodada de investigações foi uma breve análise do código, na qual encontrei algumas práticas muito ruins que desperdiçavam memória da aplicação, uso de rede e tinham baixa manutenibilidade:

Screenshot de código mostrando más práticas

Mas ainda assim, não estava nem um passo mais perto dos deadlocks. Fui para casa e assisti a um curso do Pluralsight sobre deadlocks no ônibus de volta e em casa. Isso me deu todas as ferramentas necessárias para resolver este problema, pois me ensinou os tipos de bloqueios usados pelo SQL, sua granularidade e especialmente como capturar uma representação visual de deadlocks usando o SQL Profiler (evento de grafo).

Captura de deadlock no SQL Profiler

A Solução

Os grafos que o SQL Profiler me deu para quase todos os deadlocks eram similares a este:

Grafo de deadlock mostrando bloqueios de intervalo de chaves

Ótima representação, não é? Não apenas desenha quem está bloqueando o quê, mas também fornece o tipo de bloqueios que conflitaram. O que era estranho no diagnóstico era este “Request Mode: RangeS-S”, que significa um bloqueio de intervalo de chaves compartilhado. Por que estávamos obtendo tal bloqueio?

Bloqueios de intervalo de chaves:

Protege o intervalo de linhas lidas por uma query ao usar o nível de isolamento de transação serializável. Garante que outras transações não possam inserir linhas que se qualificariam para as queries da transação serializável se as queries fossem executadas novamente.

Lembre que o bloqueio que obtivemos no grafo de deadlock é de um nível de transação Serializável. Esta é a definição:

  • Serializável — O nível mais alto onde as transações são completamente isoladas umas das outras. O Motor de Banco de Dados SQL Server mantém bloqueios de leitura e escrita adquiridos nos dados selecionados para serem liberados no final da transação. Bloqueios de intervalo são adquiridos quando uma operação SELECT usa uma cláusula WHERE com intervalo, especialmente para evitar leituras fantasmas.

Tudo bem, ainda muito estranho. Por que a transação estava usando o nível de isolamento de transação mais restritivo? Mostrei minha descoberta aos DBAs e eles ainda culparam a aplicação. Perguntei aos desenvolvedores e eles culparam o banco de dados.

Então verificamos o nível de isolamento padrão no banco de dados e estava como “ReadCommited”, o que estava correto. Então meu escopo era: por que algumas transações estavam como serializáveis?

Tive uma epifania e lembrei que estávamos usando COM+, então pesquisei “nível de isolamento de transação padrão do COM+” e obtive isto:

Configuração COM+ mostrando nível de isolamento

Então era apenas o nível de isolamento padrão do COM+. Mudar para um nível de isolamento diferente do padrão parou os deadlocks que estavam ocorrendo, pois agora os bloqueios não eram tão restritivos.

Conclusão

Esperançosamente, aqui você obteve uma das suas primeiras exposições a um pouco dos internos dos níveis de transação, bloqueio no SQL Server e também sobre como capturar eventos de deadlock se necessário.

“Às vezes, os problemas caem nas fronteiras entre diferentes papéis. Neste caso, entre os DBAs e os desenvolvedores. Acredito que uma atitude mais colaborativa pode ajudá-lo a cruzar as fronteiras para resolver o problema para sua empresa.”

Principais Aprendizados:

  • Entender os níveis de isolamento de transação e seu impacto no bloqueio
  • Usar o SQL Profiler para capturar e analisar grafos de deadlock
  • Reconhecer que problemas podem abranger múltiplas camadas de tecnologia (framework da aplicação + banco de dados)
  • A importância da resolução colaborativa de problemas entre diferentes papéis técnicos