Minimizando deadlocks

Embora deadlocks não possam ser completamente evitados, seguir certas convenções de codificação pode minimizar a chance de gerar um deadlock. Minimizar deadlocks pode aumentar a taxa de transferência da transação e pode reduzir a sobrecarga do sistema pois poucas transações são:

  • Revertidas, desfazendo todo o trabalho executado pela transação.

  • Reenviadas por aplicativos pois elas foram revertidas quando bloqueadas.

Para ajudar a minimizar deadlocks:

  • Acesse objetos na mesma ordem.

  • Evite a interação de usuário durante as transações.

  • Mantenha as transações curtas e em um lote.

  • Use um nível de isolamento inferior.

  • Use um nível de isolamento com base em controle de versão de linha

    • Configure a opção de banco de dados READ_COMMITTED_SNAPSHOT em ON, para habilitar que as transações confirmadas por leitura utilizem controle de versão de linha.

    • Use transação de isolamento de instantâneo

  • Use associações de saída.

Acesse objetos na mesma ordem.

Se todas as transações simultâneas acessarem objetos na mesma ordem, haverá menos chance de ocorrerem deadlocks. Por exemplo, se duas transações simultâneas conseguirem um bloqueio na tabela Supplier e depois na tabela Part , uma transação é bloqueada na tabela Supplier até que a outra transação seja terminada. Após a primeira transação ser confirmada ou revertida, a segunda continua e um deadlock não acontece. Usar procedimentos armazenados para todas as modificações de dados pode padronizar a ordem de acesso dos objetos.

Diagrama mostrando impedimento do deadlock de transação

Evite usar interação nas transações

Evite escrever transações que incluam interação de usuário, pois a velocidade de lotes executados sem intervenção de usuário é muito mais rápida que a velocidade que um usuário deve responder manualmente às consultas, como por exemplo, responder a um prompt para um parâmetro solicitado por um aplicativo. Por exemplo, se uma transação estiver esperando por entrada de usuário e o usuário sai para almoçar ou vai para casa durante o fim de semana, esse mesmo usuário atrasa o término da transação. Isto degrada a taxa de transferência do sistema, pois quaisquer bloqueios mantidos pela transação somente são liberados quando a transação é confirmada ou revertida. Até mesmo se uma situação de deadlock não surgir, outras transações que acessem os mesmos recursos serão bloqueadas enquanto esperam pela conclusão da transação.

Mantenha as transações curtas e em um lote.

Um deadlock ocorre tipicamente quando várias transações demoradas são executadas simultaneamente no mesmo banco de dados. Quanto mais longa a transação, por mais tempo as atualizações e bloqueios exclusivos são mantidos, bloqueando outras atividades, e levando à possíveis situações de deadlock.

Manter as transações em um lote minimiza as viagens de ida-e-volta de rede durante uma transação, reduzindo possíveis retardos ao completar a transação e liberando bloqueios.

Use um nível inferior de isolamento

Determine se uma transação pode ser executada em um nível inferior de isolamento. Implementar confirmação por leitura permite que uma transação leia dados lidos anteriormente (não modificados) por outra transação, sem esperar pela conclusão da primeira transação. Usar um nível de isolamento inferior, como a leitura confirmada, mantém bloqueios compartilhados por uma período mais curto que um nível de isolamento maior, como o serializável. Isto reduz a contenção de bloqueio.

Use um nível de isolamento com base em controle de versão de linha

Quando a opção READ_COMMITTED_SNAPSHOT do banco de dados é configurada em ON, uma transação em execução sob o nível de isolamento de leitura confirmada utiliza controle de versão de linha em vez de bloqueios compartilhados durante operações de leitura.

ObservaçãoObservação

Alguns aplicativos dependem de um comportamento de bloqueio e desbloqueio de isolamento confirmado por leitura. Para estes aplicativos, algumas alterações são necessárias antes que essa opção possa ser habilitada.

O isolamento de instantâneo também usa controle de versão de linha, o qual não usa bloqueios compartilhados durante operações de leitura. Antes que uma transação possa ser executada sob um isolamento de instantâneo, a opção ALLOW_SNAPSHOT_ISOLATION do banco de dados deve ser configurada em ON.

Implemente estes níveis de isolamento para minimizar deadlocks, que podem ocorrer entre as operações de leitura e gravação.

Use associações de saída.

Usar associações de saída usando, faz com que duas ou mais conexões abertas pelo mesmo aplicativo possam cooperar entre si. Qualquer bloqueio adquirido pelas conexões secundárias é mantido como se tivessem sido adquiridos pela conexão primária, e vice-versa. Portanto, eles não bloqueiam um ao outro.