Estou tentando entender / aprender a rastrear os detalhes de uma sessão bloqueada.
Então, eu criei a seguinte configuração:
create table foo (id integer not null primary key, some_data varchar(20));
insert into foo values (1, 'foo');
commit;
Agora eu me conecto ao banco de dados duas vezes de dois clientes diferentes.
A primeira sessão emite:
begin transaction
update foo set some_data = 'update'
where id = 1;
Eu explicitamente não confirmo lá para manter os bloqueios.
Na segunda sessão, emito a mesma declaração e, é claro, que se espera devido ao bloqueio. Agora estou tentando usar as diferentes consultas flutuando para ver se a sessão 2 está aguardando a foo
tabela.
sp_who2
mostra o seguinte (removi algumas colunas para mostrar apenas as informações importantes):
SPID Status BlkBy | DBName | Comando SPID IDENTIFICAÇÃO DO PEDIDO ----- + -------------- + ------- + ---------- + ---------- -------- + ------ + ---------- 52 dormindo | . | foodb | AGUARDANDO COMANDO | 52 0 0 53 dormindo | . | foodb | AGUARDANDO COMANDO | 53 0 0 54 SUSPENSO | 52 foodb | ATUALIZAÇÃO | 54 0 0 56 RUNNABLE | . | foodb | SELECIONAR EM | 56 0 0
Isso é esperado, a sessão 54 é bloqueada pelas alterações não confirmadas da sessão 52.
A consulta sys.dm_os_waiting_tasks
também mostra isso. A declaração:
select session_id, wait_type, resource_address, resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null;
retorna:
session_id | wait_type | resource_address | resource_description ----------- + ----------- + -------------------- + ----- -------------------------------------------------- -------------------------- 54 LCK_M_X 0x000000002a35cd40 | hobtid do bloqueio do teclado = 72057594046054400 dbid = 6 id = modo lock4ed1dd780 = X AssociatedObjectId = 72057594046054400
Novamente, isso é esperado.
Meu problema é que não consigo descobrir como encontrar o nome real do objeto que a sessão 54 está aguardando.
Eu encontrei várias consultas que estão ingressando sys.dm_tran_locks
e sys.dm_os_waiting_tasks
assim:
SELECT ....
FROM sys.dm_tran_locks AS l
JOIN sys.dm_os_waiting_tasks AS wt ON wt.resource_address = l.lock_owner_address
Mas no meu cenário de teste acima, essa junção não retorna nada. Portanto, essa junção está errada ou dm_tran_locks
não contém as informações que estou procurando.
Então, o que estou procurando é uma consulta que retorne algo como:
"a sessão 54 está aguardando um bloqueio na tabelafoo
".
Algumas informações básicas:
O problema da vida real que estou tentando resolver é um pouco mais complicado, mas resume-se à pergunta "em que mesa está aguardando a sessão 54". O problema em questão envolve um procedimento armazenado amplo que atualiza várias tabelas e uma seleção de uma exibição que acessa algumas dessas tabelas. A select
instrução está bloqueada, apesar de termos o isolamento da captura instantânea e a leitura da captura instantânea confirmada ativada. Descobrir por que a seleção está bloqueada (o que eu pensei que não seria possível se o isolamento de captura instantânea estiver ativado) será o próximo passo.
Como primeiro passo, gostaria de descobrir o que a sessão está esperando.