Como verificar quais bloqueios são mantidos em uma tabela

158

Como podemos verificar quais bloqueios de banco de dados são aplicados em quais linhas em um lote de consulta?

Alguma ferramenta que destaca o bloqueio no nível da linha da tabela em tempo real?

DB: SQL Server 2005

usman shaheen
fonte

Respostas:

118

Para adicionar às outras respostas, sp_locktambém pode ser usado para despejar informações completas de bloqueio em todos os processos em execução. A saída pode ser esmagadora, mas se você quiser saber exatamente o que está bloqueado, é uma tarefa valiosa para executar. Eu costumo usá-lo junto sp_who2para rapidamente me concentrar nos problemas de bloqueio.

Existem várias versões diferentes de sp_lockprocedimentos "mais amigáveis" disponíveis online, dependendo da versão do SQL Server em questão.

No seu caso, para o SQL Server 2005, ele sp_lockainda está disponível, mas está obsoleto. Portanto, agora é recomendável usar a sys.dm_tran_locksexibição para esse tipo de coisa. Você pode encontrar um exemplo de como "rolar sua própria" função sp_lock aqui .

mwigdahl
fonte
116

Isso não mostra exatamente quais linhas estão bloqueadas, mas isso pode ser útil para você.

Você pode verificar quais instruções estão bloqueadas executando este:

select cmd,* from sys.sysprocesses
where blocked > 0

Também informará o que cada bloco está esperando. Portanto, você pode rastrear isso até ver qual instrução causou o primeiro bloco que causou os outros blocos.

Edite para adicionar comentário de @MikeBlandford :

A coluna bloqueada indica o spid do processo de bloqueio. Você pode executar o kill {spid} para corrigi-lo.

Brian R. Bondy
fonte
7
A coluna bloqueada indica o spid do processo de bloqueio. Você pode executar o kill {spid} para corrigi-lo.
Mike Blandford
52

Você pode encontrar bloqueios atuais na sua tabela seguindo a consulta.

USE yourdatabase;
GO

SELECT * FROM sys.dm_tran_locks
  WHERE resource_database_id = DB_ID()
  AND resource_associated_entity_id = OBJECT_ID(N'dbo.yourtablename');

Consulte sys.dm_tran_locks

Se existirem várias instâncias do mesmo request_owner_type , a coluna request_owner_id será usada para distinguir cada instância. Para transações distribuídas, as colunas request_owner_type e request_owner_guid mostrarão as diferentes informações da entidade.

Por exemplo, a Sessão S1 possui um bloqueio compartilhado na Tabela1; e a transação T1, que está sendo executada na sessão S1, também possui um bloqueio compartilhado na Tabela1. Nesse caso, a coluna resource_description retornada por sys.dm_tran_locks mostrará duas instâncias do mesmo recurso. A coluna request_owner_type mostrará uma instância como uma sessão e a outra como uma transação. Além disso, a coluna resource_owner_id terá valores diferentes.

Somnath Muluk
fonte
36

Eu uso um Dynamic Management View (DMV) para capturar bloqueios, bem como o object_id ou partition_id do item que está bloqueado.

(DEVE mudar para o banco de dados que você deseja observar para obter object_id)

SELECT 
     TL.resource_type,
     TL.resource_database_id,
     TL.resource_associated_entity_id,
     TL.request_mode,
     TL.request_session_id,
     WT.blocking_session_id,
     O.name AS [object name],
     O.type_desc AS [object descr],
     P.partition_id AS [partition id],
     P.rows AS [partition/page rows],
     AU.type_desc AS [index descr],
     AU.container_id AS [index/page container_id]
FROM sys.dm_tran_locks AS TL
INNER JOIN sys.dm_os_waiting_tasks AS WT 
 ON TL.lock_owner_address = WT.resource_address
LEFT OUTER JOIN sys.objects AS O 
 ON O.object_id = TL.resource_associated_entity_id
LEFT OUTER JOIN sys.partitions AS P 
 ON P.hobt_id = TL.resource_associated_entity_id
LEFT OUTER JOIN sys.allocation_units AS AU 
 ON AU.allocation_unit_id = TL.resource_associated_entity_id;
Jon
fonte
Estou tentando usar esta declaração para descobrir os objetos que um processo está esperando. Eu posso ver claramente uma sessão aguardando outra usando sp_who2e entrando sys.dm_os_waiting_task(ambas tentando atualizar a mesma tabela). Mas sua declaração não retorna nenhuma linha. Alguma ideia?
precisa saber é o seguinte
17

Você também pode usar o sp_who2procedimento armazenado interno para obter os processos atuais de bloqueio e bloqueio em uma instância do SQL Server. Normalmente, você executaria isso ao lado de uma instância do SQL Profiler para encontrar um processo de bloqueio e observar o comando mais recente que spid emitido no profiler.

Neil Barnwell
fonte
5

Você pode encontrar detalhes através do script abaixo.

-- List all Locks of the Current Database 
SELECT TL.resource_type AS ResType 
      ,TL.resource_description AS ResDescr 
      ,TL.request_mode AS ReqMode 
      ,TL.request_type AS ReqType 
      ,TL.request_status AS ReqStatus 
      ,TL.request_owner_type AS ReqOwnerType 
      ,TAT.[name] AS TransName 
      ,TAT.transaction_begin_time AS TransBegin 
      ,DATEDIFF(ss, TAT.transaction_begin_time, GETDATE()) AS TransDura 
      ,ES.session_id AS S_Id 
      ,ES.login_name AS LoginName 
      ,COALESCE(OBJ.name, PAROBJ.name) AS ObjectName 
      ,PARIDX.name AS IndexName 
      ,ES.host_name AS HostName 
      ,ES.program_name AS ProgramName 
FROM sys.dm_tran_locks AS TL 
     INNER JOIN sys.dm_exec_sessions AS ES 
         ON TL.request_session_id = ES.session_id 
     LEFT JOIN sys.dm_tran_active_transactions AS TAT 
         ON TL.request_owner_id = TAT.transaction_id 
            AND TL.request_owner_type = 'TRANSACTION' 
     LEFT JOIN sys.objects AS OBJ 
         ON TL.resource_associated_entity_id = OBJ.object_id 
            AND TL.resource_type = 'OBJECT' 
     LEFT JOIN sys.partitions AS PAR 
         ON TL.resource_associated_entity_id = PAR.hobt_id 
            AND TL.resource_type IN ('PAGE', 'KEY', 'RID', 'HOBT') 
     LEFT JOIN sys.objects AS PAROBJ 
         ON PAR.object_id = PAROBJ.object_id 
     LEFT JOIN sys.indexes AS PARIDX 
         ON PAR.object_id = PARIDX.object_id 
            AND PAR.index_id = PARIDX.index_id 
WHERE TL.resource_database_id  = DB_ID() 
      AND ES.session_id <> @@Spid -- Exclude "my" session 
      -- optional filter  
      AND TL.request_mode <> 'S' -- Exclude simple shared locks 
ORDER BY TL.resource_type 
        ,TL.request_mode 
        ,TL.request_type 
        ,TL.request_status 
        ,ObjectName 
        ,ES.login_name;



--TSQL commands
SELECT 
       db_name(rsc_dbid) AS 'DATABASE_NAME',
       case rsc_type when 1 then 'null'
                             when 2 then 'DATABASE' 
                             WHEN 3 THEN 'FILE'
                             WHEN 4 THEN 'INDEX'
                             WHEN 5 THEN 'TABLE'
                             WHEN 6 THEN 'PAGE'
                             WHEN 7 THEN 'KEY'
                             WHEN 8 THEN 'EXTEND'
                             WHEN 9 THEN 'RID ( ROW ID)'
                             WHEN 10 THEN 'APPLICATION' end  AS 'REQUEST_TYPE',

       CASE req_ownertype WHEN 1 THEN 'TRANSACTION'
                                     WHEN 2 THEN 'CURSOR'
                                     WHEN 3 THEN 'SESSION'
                                     WHEN 4 THEN 'ExSESSION' END AS 'REQUEST_OWNERTYPE',

       OBJECT_NAME(rsc_objid ,rsc_dbid) AS 'OBJECT_NAME', 
       PROCESS.HOSTNAME , 
       PROCESS.program_name , 
       PROCESS.nt_domain , 
       PROCESS.nt_username , 
       PROCESS.program_name ,
       SQLTEXT.text 
FROM sys.syslockinfo LOCK JOIN 
     sys.sysprocesses PROCESS
  ON LOCK.req_spid = PROCESS.spid
CROSS APPLY sys.dm_exec_sql_text(PROCESS.SQL_HANDLE) SQLTEXT
where 1=1
and db_name(rsc_dbid) = db_name()



--Lock on a specific object
SELECT * 
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID()
AND resource_associated_entity_id = object_id('Specific Table');
Metin Atalay
fonte