Deadlock

Um deadlock acontece quando duas ou mais tarefas bloqueiam uma à outra permanentemente, sendo que cada uma tem o bloqueio de um recurso, que a outra tarefa está tentando bloquear. Por exemplo:

  • A transação A adquire um bloqueio compartilhado da linha 1.

  • A transação B adquire um bloqueio compartilhado da linha 2.

  • A transação A agora solicita um bloqueio exclusivo na linha 2 e é bloqueado até que a transação B termine e libere o bloqueio compartilhado que tem na linha 2.

  • A transação B agora solicita um bloqueio exclusivo na linha 1 e é bloqueado até que a transação A termine e libere o bloqueio compartilhado que tem na linha 1.

A transação A não pode terminar até que a transação B termine, mas a transação B está bloqueada pela transação A. Essa condição é também chamada de dependência cíclica: a transação A tem uma dependência da transação B, e a transação B fecha o círculo tendo uma dependência da transação A.

Ambas as transações em um deadlock esperarão indefinidamente, a menos que o deadlock seja quebrado por um processo externo. O monitor de deadlock do Microsoft Mecanismo de banco de dados do SQL Server verifica periodicamente as tarefas que estão em um deadlock. Se o monitor detectar uma dependência cíclica, ele escolhe uma das tarefas como vítima e termina sua transação com um erro. Isso permite que a outra tarefa complete sua transação. O aplicativo com a transação que terminou com um erro pode repetir a transação, a qual normalmente é concluída depois que a outra transação em deadlock é encerrada.

Usando certas convenções de codificação em aplicativos reduz a chance de que os aplicativos causarão deadlocks. Para obter mais informações, consulte Minimizando deadlocks.

O deadlock é freqüentemente confundido com bloqueio normal. Quando uma transação solicita um bloqueio em um recurso bloqueado por outra transação, a transação solicitante espera até que o bloqueio seja liberado. Por padrão, as transações SQL Server não têm tempo limite, a menos que LOCK_TIMEOUT seja configurado. A transação solicitante é bloqueada, não em deadlock, por que ela não fez nada para bloquear a transação que deve o bloqueio. Finalmente, a transação proprietária vai terminar e liberar o bloqueio e a transação solicitante terá o bloqueio atribuído e processado.

Os deadlocks às vezes são chamados de abraço mortal.

Deadlock é uma condição que pode ocorrer em qualquer sistema com vários threads, não só em sistemas de gerenciamento de banco de dados relacional, e pode ocorrer para outros recursos, além de bloqueios de objetos em bancos de dados. Por exemplo, um thread em um sistema operacional de vários threads pode adquirir um ou mais recursos, como bloqueios de memória. Se o recurso sendo adquirido é atualmente propriedade de outro thread, o primeiro thread pode ter que esperar o thread proprietário liberar o recurso alvo. O thread em espera tem uma dependência do thread proprietário para aquele recurso em particular. Em uma instância do Mecanismo de Banco de Dados, sessões podem fazer um deadlock ao adquirir recursos que não são de banco de dados, como memória ou threads.

Diagrama mostrando o deadlock de transação

Na ilustração, a transação T1 tem uma dependência da transação T2 para o recurso de bloqueio de tabela Part. Da mesma forma, a transação T2 tem uma dependência da transação T1 para o recurso de bloqueio de tabela Supplier. Devido a essas dependências formarem um ciclo, há um deadlock entre as transações T1 e T2.

Os deadlocks também podem ocorrer quando uma tabela é particionada e a configuração LOCK_ESCALATION do ALTER TABLE é configurada para AUTO. Quando a LOCK_ESCALATION é configurada para AUTO, a simultaneidade aumenta ao permitir que o Mecanismo de Banco de Dados bloqueie partições de tabela no nível de HoBT em vez de no nível de TABLE. Entretanto, quando transações separadas mantêm bloqueios de partição em uma tabela e querem um bloqueio em algum lugar de outra partição de transações, isso causa um deadlock. Esse tipo de deadlock pode ser evitado configurando LOCK_ESCALATION para TABLE; embora essa configuração irá reduzir a simultaneidade forçando as atualizações extensas em uma partição a esperarem por um bloqueio de tabela.