Você está na página 1de 12

Detectando e encerrando deadlocks

SQL Server 2008 R2


Other Versions

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. O seguinte gráfico apresenta uma exibição de alto nível
de um estado de deadlock em que:

• A tarefa T1 tem um bloqueio no recurso R1 (indicado pela seta de R1 para T1) e


solicitou um bloqueio no recurso R2 (indicado pela seta de T1 para R2).
• A tarefa T2 tem um bloqueio no recurso R2 (indicado pela seta de R2 a T2) e
solicitou um bloqueio no recurso R1 (indicado pela seta de T2 a R1).
• Como nenhuma tarefa pode continuar até que um recurso esteja disponível e
nenhum recurso pode ser liberado até que uma tarefa continue, ocorre um
estado de deadlock.

O Mecanismo de banco de dados do SQL Server detecta ciclos de deadlock


automaticamente dentro do SQL Server. O Mecanismo de Banco de Dados escolhe uma
das sessões como vítima de deadlock e a transação atual é encerrada com um erro para
quebrar o deadlock.

Recursos que podem acarretar deadlock


Cada sessão de usuário pode ter uma ou mais tarefas sendo executadas em seu nome,
sendo que cada tarefa pode adquirir ou aguardar para adquirir uma variedade de
recursos. Os tipos de recursos a seguir podem causar bloqueio que pode resultar em um
deadlock.

• Bloqueios. A espera para adquirir bloqueios em recursos, como objetos,


páginas, linhas, metadados e aplicativos pode causar deadlock. Por exemplo, a
transação T1 tem um bloqueio compartilhado (S) na linha r1 e está esperando
para obter um bloqueio exclusivo (X) em r2. A transação T2 tem um bloqueio
compartilhado (S) na linha r1 e está esperando para obter um bloqueio exclusivo
(X) em r1. Isso resulta em um ciclo de bloqueio no qual T1 e T2 esperam que
uma libere os recursos bloqueados da outra.
• Threads de trabalho Uma tarefa em fila aguardando um thread de trabalho
pode causar um deadlock. Se a tarefa em fila possuir recursos que estão
bloqueando todos os threads de trabalhado, haverá um deadlock. Por exemplo, a
sessão S1 inicia uma transação e adquire um bloqueio compartilhado (S) na
linha r1 e, depois, fica suspenso. As sessões ativas em execução em todos os
threads de trabalhado disponíveis estão tentando adquirir bloqueios exclusivos
(X) na linha r1. Como a sessão S1 não pode adquirir um thread de trabalho, ela
não pode confirmar a transação e liberar o bloqueio na linha r1. Isso resulta em
um deadlock.
• Memória. Quando solicitações simultâneas estão esperando por concessões de
memória que não podem ser satisfeitas com a memória disponível, pode ocorrer
um deadlock. Por exemplo, duas consultas simultâneas, Q1 e Q2, são
executadas como funções definidas pelo usuário que adquirem 10MB e 20MB de
memória, respectivamente. Se cada consulta precisar de 30MB e a memória
disponível total for de 20MB, Q1 e Q2 deverão esperar uma pela outra para
liberar memória. Isso resulta em um deadlock.
• Recursos relacionados à execução de consultas paralelas Threads de
coordenação, produção ou consumo associados a uma porta de troca podem
bloquear um ao outro causando um deadlock, normalmente ao incluir pelo
menos um outro processo que não faz parte da consulta paralela. Além disso,
quando uma consulta paralela começa a ser executada, o SQL Server determina
o grau de paralelismo, ou o número de threads de trabalho, com base na carga
de trabalho atual. Se a carga de trabalho do sistema for alterada
inesperadamente, por exemplo, quando novas consultas forem executadas no
servidor ou o sistema ficar sem threads de trabalho, poderá ocorrer um
deadlock.
• Recursos de vários conjuntos de resultados ativos (MARS). Esses recursos
são usados para controlar a intercalação de várias solicitações ativas em MARS
(consulte Ambiente de execução em lote e MARS).
o Recurso do usuário. Quando um thread está esperando por um recurso
que é potencialmente controlado por um aplicativo de usuário, o recurso
é considerado como externo ou recurso de usuário e é tratado como um
bloqueio.
o Mutex de sessão. As tarefas que estão sendo executadas em uma
sessão são intercaladas, ou seja, apenas uma tarefa pode ser executada
na sessão em um determinado momento. Antes de a tarefa ser
executada, deve ter acesso exclusivo ao mutex de sessão.
o Mutex de transação. Todas as tarefas que estão sendo executadas em
uma transação são intercaladas, ou seja, somente uma tarefa pode ser
executada na transação em um determinado momento. Antes da tarefa
ser executada, deve ter acesso exclusivo ao mutex de transação.

Para que uma tarefa seja executada em MARS, ela deve adquirir o mutex da
sessão. Se a tarefa estiver sendo executada em uma transação, deverá adquirir
o mutex de transação. Isso garante que apenas uma tarefa esteja ativa em um
determinado momento, sessão e transação. Quando os mutexes solicitados
forem adquiridos, a tarefa poderá ser executada. Quando a tarefa termina, ou
está no meio da solicitação, primeiro ela libera o mutex de transação e, depois, o
mutex de sessão em ordem reversa de aquisição. Porém, podem ocorrer
deadlocks com esses recursos. No exemplo de código a seguir, duas tarefas,
solicitação de usuário U1 e solicitação de usuário U2, estão sendo executadas na
mesma sessão.

Copiar

U1: Rs1=Command1.Execute("insert sometable EXEC usp_someproc");


U2: Rs2=Command2.Execute("select colA from sometable");

O procedimento armazenado que está sendo executado na solicitação U1


adquiriu o mutex de sessão. Se o procedimento armazenado levar muito tempo
para ser executado, o Mecanismo de Banco de Dados presumirá que o
procedimento armazenado está esperando uma entrada do usuário. A solicitação
de usuário U2 está esperando pelo mutex de sessão, enquanto o usuário está
esperando pelo conjunto de resultados de U2, e U1 está esperando por um
recurso de usuário. Esse estado de deadlock é logicamente ilustrado como:

Detecção de deadlock
Todos os recursos listados na seção anterior participam do esquema de detecção de
deadlock Mecanismo de Banco de Dados. A detecção de deadlock é executada por um
thread de monitor de bloqueio que periodicamente inicia uma pesquisa por todas as
tarefas em uma instância do Mecanismo de Banco de Dados. Os seguintes pontos
descrevem o processo de pesquisa:

• O intervalo padrão é de 5 segundos.


• Se o thread de monitor de bloqueio localizar deadlocks, o intervalo de detecção
de deadlock diminuirá de 5 segundos para até 100 milissegundos, dependendo
da frequência de deadlocks.
• Se o thread de monitor de bloqueio parar de localizar deadlocks, o Mecanismo
de Banco de Dados aumentará os intervalos entre pesquisas para 5 segundos.
• Se um deadlock tiver sido detectado há pouco tempo, presume-se que os
próximos threads que precisarem esperar por um bloqueio estejam entrando no
ciclo de deadlock. O primeiro par de esperas de bloqueio, após a detecção de um
deadlock, dispara imediatamente uma pesquisa de deadlock em vez de aguardar
pelo próximo intervalo de detecção de deadlock. Por exemplo, se o intervalo
atual for de 5 segundos, e um deadlock tiver sido detectado há pouco tempo, a
próxima espera de bloqueio iniciará o detector de deadlock imediatamente. Se
essa espera de bloqueio fizer parte de um deadlock, será detectada
imediatamente em vez de durante a próxima pesquisa de deadlock.

Normalmente, o Mecanismo de Banco de Dados executa somente a detecção periódica


de deadlock. Como o número de deadlocks encontrado no sistema geralmente é
pequeno, a detecção periódica de deadlock ajuda a reduzir a sobrecarga de detecção de
deadlock no sistema.

Quando o monitor de bloqueio inicia a pesquisa de deadlock para um determinado


thread, ele identifica o recurso em que o thread está esperando. O monitor de bloqueio
localiza o proprietário desse recurso em particular e, recursivamente, continua a
pesquisa de deadlock para esses threads até encontrar um ciclo. Um ciclo identificado
dessa maneira forma um deadlock.

Depois que um deadlock é detectado, o Mecanismo de Banco de Dados encerra esse


deadlock escolhendo um dos threads como uma vítima de deadlock. O Mecanismo de
Banco de Dados encerra o lote atual que está sendo executado para o thread, reverte a
transação da vítima de deadlock e retorna um erro 1205 para o aplicativo. A reversão da
transação da vítima de deadlock libera todos os bloqueios mantidos pela transação. Isso
permite que as transações dos outros threads sejam desbloqueadas e prossigam. O erro
1205 da vítima de deadlock registra informações sobre os threads e recursos envolvidos
em um deadlock no log de erros.

Por padrão, o Mecanismo de Banco de Dados escolhe a sessão que está executando a
transação mais fácil de ser revertida como a vítima de deadlock. Alternativamente, um
usuário pode especificar a prioridade de sessões em uma situação de deadlock usando a
instrução SET DEADLOCK_PRIORITY. O DEADLOCK_PRIORITY pode ser definida como
LOW, NORMAL ou HIGH ou, alternativamente, pode ser definido como qualquer valor de
inteiro no intervalo (-10 a 10). A prioridade de deadlock assume NORMAL como padrão.
Se duas sessões tiverem prioridades de deadlock diferentes, a sessão com a prioridade
mais baixa será escolhida como a vítima de deadlock. Se ambas as sessões tiverem a
mesma prioridade de deadlock, a sessão com a transação menos dispendiosa para ser
revertida será escolhida. Se as sessões envolvidas no ciclo de deadlock tiverem a
mesma prioridade de deadlock e o mesmo custo, a vítima será escolhida
aleatoriamente.

Ao trabalhar com CLR, o monitor de deadlock detecta automaticamente um deadlock


para recursos de sincronização (monitores, bloqueio de leitura/gravação ou junção de
thread) acessados dentro dos procedimentos gerenciados. Entretanto, o deadlock é
resolvido ao se lançar uma exceção no procedimento selecionado como a vítima de
deadlock. É importante entender que a exceção não libera automaticamente os recursos
pertencentes à vítima; os recursos devem ser liberados explicitamente. Em consonância
com o comportamento de exceção, a exceção usada para identificar uma vítima de
deadlock pode ser capturada e ignorada.

Ferramentas de informações sobre deadlock


Para exibir informações sobre deadlock, o Mecanismo de Banco de Dados fornece
ferramentas de monitoração na forma de dois sinalizadores de rastreamento e o evento
gráfico de deadlock no SQL Server Profiler.

Sinalizadores de rastreamento 1204 e 1222

Quando acontecem deadlocks, os sinalizadores de rastreamento 1204 e 1222 retornam


informações captadas no log de erros SQL Server 2005. O sinalizador de rastreamento
1204 relata informações de deadlock formatadas por cada nó envolvido no deadlock. O
sinalizador de rastreamento 1222 formata informações de deadlock, primeiro por
processos e depois por recursos. É possível permitir que ambos os sinalizadores de
rastreamento obtenham duas representações do mesmo evento de deadlock.

Além de definir as propriedades dos sinalizadores de rastreamento 1204 e 1222, a


tabela a seguir também mostra suas semelhanças e diferenças.

Proprieda Sinalizadores de Apenas sinalizador Apenas sinalizador de


de rastreamento 1204 e de rastreamento rastreamento 1222
1222 1204
Formato de A saída captada no log de Focado nos nós Retorna informações em
saída erros do SQL Server 2005. envolvidos no um formato parecido
deadlock. Cada nó com XML que não está
tem uma seção em conformidade com
dedicada e a seção uma definição de
final descreve a esquema XML (XSD). O
vítima de deadlock. formato tem três seções
principais. A primeira
seção declara a vítima de
deadlock. A segunda
seção descreve cada
processo envolvido no
deadlock. A terceira
seção descreve os
recursos que são
sinônimos com os nós no
sinalizador de
rastreamento 1204.
Identifican SPID:<x> ECID:<x>. Node. Representa o deadlock victim.
do Identifica o thread de ID de número de entrada Representa o endereço
atributos processo de sistema em na cadeia de de memória físico da
casos de processos deadlock. tarefa (consulte
paralelos. A entrada sys.dm_os_tasks (Transact-
SPID:<x> ECID:0, em que Lists. O proprietário SQL)) selecionada como
<x> é substituído pelo valor do bloqueio pode vítima de deadlock. Pode
SPID, representa o thread ser 0 (zero) no caso de
principal. A entrada fazer parte destas um deadlock não
SPID:<x> ECID:<y>, em listas: resolvido. Uma tarefa
que <x> é substituído pelo que está sendo revertida
valor SPID e <y> é maior • Grant não pode ser escolhida
que 0, representa os sub- List. como vítima de deadlock.
threads para o mesmo SPID. Enumera os
proprietários executionstack.
BatchID (sbid para o atuais do Representa o código
sinalizador de rastreamento recurso. Transact-SQL que está
1222). Identifica o lote do • Conv sendo executado no
qual a execução de código ert List. momento em que o
está solicitando ou Enumera os deadlock ocorre.
mantendo um bloqueio. proprietários
Quando vários conjuntos de atuais que priority. Representa a
resultados ativos (MARS) estão prioridade do deadlock.
estão desabilitados, o valor tentando Em determinados casos,
BatchID é 0. Quando MARS converter o Mecanismo de Banco
estão habilitados, o valor de seus de Dados pode optar por
lotes ativos é 1 para n. Se bloqueios em alterar a prioridade de
não houver lotes ativos na um nível deadlock para uma
sessão, BatchID será 0. mais alto. duração curta para obter

• Wait uma simultaneidade


Mode. Especifica o tipo de List. melhor.
bloqueio de um Enumera as
determinado recurso que é logused. Espaço de log
novas
solicitado, concedido ou usado pela tarefa.
solicitações
aguardado por um thread. de bloqueio
O Mode pode ser IS owner id. A ID da
do recurso.
(Tentativa Compartilhada), transação que tem

S (Compartilhado), U controle da solicitação.


Statement Type.
(Atualização), IX (Exclusivo Descreve o tipo de
status O estado da
da Tentativa), SIX instrução DML
tarefa. Pode ser um dos
(Exclusivo da Tentativa (SELECT, INSERT,
seguintes valores:
Compartilhado) e X UPDATE ou DELETE)
(Exclusivo). Para obter mais em que os threads
• pending.
informações, consulte Modos têm permissões.
Esperando por
de bloqueio .
um thread de
Victim Resource
Line # (line para o trabalho.
Owner. Especifica o
sinalizador de rastreamento thread participante • runnable.
1222). Lista o número de que o SQL Server Pronto para ser
linha no lote atual de escolhe como a executado, mas
instruções que estava vítima para quebrar esperando por
sendo executado quando o o ciclo de deadlock. um quantum.
• running.
deadlock aconteceu. O thread escolhido e Atualmente em
todos os sub-threads execução no
Input Buf (inputbuf para o existentes são agendador.
sinalizador de rastreamento encerrados.
• suspende
1222). Lista todas as
d. A execução
instruções no lote atual. Next Branch.
está suspensa.
Representa os dois
• done. A
ou mais sub-threads
tarefa foi
do mesmo SPID
concluída.
envolvidos no ciclo
• spinloop.
de deadlock.
Esperando que
um spinlock seja
liberado.

waitresource. O recurso
requerido pela tarefa.

waittime. O tempo em
milissegundos de espera
pelo recurso.

schedulerid. O
agendador associado à
essa tarefa. Consulte
sys.dm_os_schedulers
(Transact-SQL).

hostname. O nome da
estação de trabalho.

isolationlevel. O nível
de isolamento da
transação atual.

Xactid. A ID da
transação que tem
controle da solicitação.

currentdb. A ID do
banco de dados.

lastbatchstarted. A
última vez em que um
processo cliente iniciou
uma execução em lote.

lastbatchcompleted. A
última vez em que um
processo cliente concluiu
uma execução em lote.

clientoption1 e
clientoption2. Defina as
opções nessa conexão de
cliente. Esse é um
bitmask que inclui
informações sobre
opções normalmente
controladas por
instruções SET, como
SET NOCOUNT e SET
XACTABORT.

associatedObjectId.
Representa a ID de HoBT
(heap ou árvore B).
Atributos RID. Identifica a única linha Nenhum exclusivo Nenhum exclusivo para
do recurso dentro de uma tabela na para esse sinalizador esse sinalizador de
qual um bloqueio é mantido de rastreamento. rastreamento.
ou solicitado. O RID é
representado como RID:
db_id:file_id:page_no:row_n
o. Por exemplo, RID:
6:1:20789:0.

OBJECT. Identifica a tabela


na qual um bloqueio é
mantido ou solicitado.
OBJECT é representado
como OBJECT:
db_id:object_id. Por
exemplo, TAB:
6:2009058193.

KEY. Identifica o intervalo


de chave dentro de um
índice em que um bloqueio
é mantido ou solicitado. KEY
é representado como KEY:
db_id:hobt_id (index key
hash value). Por exemplo,
KEY:
6:72057594057457664
(350007a4d329).

PAG. Identifica o recurso de


página no qual um bloqueio
é mantido ou solicitado. O
PAG é representado como
PAG: db_id:file_id:page_no.
Por exemplo, PAG:
6:1:20789.

EXT. Identifica a estrutura


de extensão. EXT é
representado como EXT:
db_id:file_id:extent_no. Por
exemplo, EXT: 6:1:9.

DB. Identifica o bloqueio de


banco de dados. DB é
representado de um dos
seguintes modos:

• DB: db_id
• DB:
db_id[BULK-OP-DB],
que identifica o
bloqueio de banco
de dados feito pelo
banco de dados de
backup.
• DB:
db_id[BULK-OP-DB],
que identifica o
bloqueio feito pelo
log de backup
daquele banco de
dados específico.

APP. Identifica o bloqueio


feito por um recurso de
aplicativo. APP é
representado por APP:
lock_resource. Por exemplo,
APP: Formf370f478.

METADATA. Representa os
recursos de metadados
envolvidos em um
deadlock. Como METADATA
tem muitos sub-recursos, o
valor retornado depende do
sub-recurso envolvido no
deadlock. Por exemplo,
METADATA.USER_TYPE
retorna user_type_id
=<integer_value>. Para
obter mais informações
sobre os recursos e sub-
recursos de METADATA,
consulte sys.dm_tran_locks
(Transact-SQL).

HOBT. Representa um heap


ou árvore B envolvida em
um deadlock.

Exemplo do sinalizador de rastreamento 1204

O exemplo a seguir mostra a saída quando o sinalizador de rastreamento 1204 é


ativado. Neste caso, a tabela em Node 1 é um heap sem índices, e a tabela em Node 2 é
um heap com índices não clusterizados. A chave de índice em Node 2 é atualizada
quando o deadlock ocorre.

Copiar
Deadlock encountered .... Printing deadlock information
Wait-for graph

Node:1

RID: 6:1:20789:0 CleanCnt:3 Mode:X Flags: 0x2


Grant List 0:
Owner:0x0315D6A0 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:55 ECID:0 XactLockInfo: 0x04D9E27C
SPID: 55 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p2
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x03A3DAD0
Mode: U SPID:54 BatchID:0 ECID:0 TaskProxy:(0x04976374) Value:0x315d200
Cost:(0/868)

Node:2

KEY: 6:72057594057457664 (350007a4d329) CleanCnt:2 Mode:X Flags: 0x0


Grant List 0:
Owner:0x0315D140 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:54 ECID:0 XactLockInfo: 0x03A3DAF4
SPID: 54 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p1
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0
Cost:(0/380)

Victim Resource Owner:


ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0
Cost:(0/380)

Exemplo do sinalizador de rastreamento 1222

O exemplo a seguir mostra a saída quando o sinalizador de rastreamento 1222 é


ativado. Neste caso, uma tabela é um heap sem índices, e a outra tabela é um heap
com um índice não clusterizado. Na segunda tabela, a chave de índice é atualizada
quando o deadlock ocorre.

Copiar
deadlock-list
deadlock victim=process689978
process-list
process id=process6891f8 taskpriority=0 logused=868
waitresource=RID: 6:1:20789:0 waittime=1359 ownerId=310444
transactionname=user_transaction
lasttranstarted=2005-09-05T11:22:42.733 XDES=0x3a3dad0
lockMode=U schedulerid=1 kpid=1952 status=suspended spid=54
sbid=0 ecid=0 priority=0 transcount=2
lastbatchstarted=2005-09-05T11:22:42.733
lastbatchcompleted=2005-09-05T11:22:42.733
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310444 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2008R2.dbo.usp_p1 line=6 stmtstart=202
sqlhandle=0x0300060013e6446b027cbb00c69600000100000000000000
UPDATE T2 SET COL1 = 3 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600856aa70f503b8104000000000000000000000000
EXEC usp_p1
inputbuf
BEGIN TRANSACTION
EXEC usp_p1
process id=process689978 taskpriority=0 logused=380
waitresource=KEY: 6:72057594057457664 (350007a4d329)
waittime=5015 ownerId=310462 transactionname=user_transaction
lasttranstarted=2005-09-05T11:22:44.077 XDES=0x4d9e258 lockMode=U
schedulerid=1 kpid=3024 status=suspended spid=55 sbid=0 ecid=0
priority=0 transcount=2 lastbatchstarted=2005-09-05T11:22:44.077
lastbatchcompleted=2005-09-05T11:22:44.077
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310462 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2008R2.dbo.usp_p2 line=6 stmtstart=200
sqlhandle=0x030006004c0a396c027cbb00c69600000100000000000000
UPDATE T1 SET COL1 = 4 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600d688e709b85f8904000000000000000000000000
EXEC usp_p2
inputbuf
BEGIN TRANSACTION
EXEC usp_p2
resource-list
ridlock fileid=1 pageid=20789 dbid=6
objectname=AdventureWorks2008R2.dbo.T2
id=lock3136940 mode=X associatedObjectId=72057594057392128
owner-list
owner id=process689978 mode=X
waiter-list
waiter id=process6891f8 mode=U requestType=wait
keylock hobtid=72057594057457664 dbid=6
objectname=AdventureWorks2008R2.dbo.T1
indexname=nci_T1_COL1 id=lock3136fc0 mode=X
associatedObjectId=72057594057457664
owner-list
owner id=process6891f8 mode=X
waiter-list
waiter id=process689978 mode=U requestType=wait

Evento gráfico de deadlock de designer de perfil

Este é um evento do SQL Server Profiler que apresenta uma representação gráfica das
tarefas e recursos envolvidos em um deadlock. O exemplo a seguir mostra a saída do
SQL Server Profiler quando o evento de gráfico de deadlock é ativado.

Para obter mais informações sobre a execução do gráfico de deadlock do SQL Server
Profiler, consulte Analisando deadlocks com o SQL Server Profiler.

Consulte também
Conceitos

Deadlock
Minimizando deadlocks