Come verificare quali blocchi si trovano su un tavolo


158

Come possiamo verificare quali blocchi del database vengono applicati su quali righe rispetto a un batch di query?

Qualsiasi strumento che evidenzia il blocco a livello di riga della tabella in tempo reale?

DB: SQL Server 2005

Risposte:


118

Per aggiungere ad altre risposte, sp_lockpuò anche essere utilizzato per scaricare informazioni di blocco completo su tutti i processi in esecuzione. L'output può essere travolgente, ma se vuoi sapere esattamente cosa è bloccato, è prezioso da eseguire. Di solito lo uso insieme sp_who2per azzerare rapidamente i problemi di blocco.

Esistono più versioni diverse di sp_lockprocedure "più amichevoli" disponibili online, a seconda della versione di SQL Server in questione.

Nel tuo caso, per SQL Server 2005, sp_lockè ancora disponibile, ma obsoleto, quindi ora è consigliabile utilizzare la sys.dm_tran_locksvista per questo tipo di cose. Puoi trovare un esempio di come "spingere la tua" funzione sp_lock qui .


116

Questo non ti mostra esattamente quali file sono bloccate, ma può esserti utile.

Puoi controllare quali istruzioni sono bloccate eseguendo questo:

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

Ti dirà anche su cosa sta aspettando ogni blocco. Quindi puoi risalire fino in fondo per vedere quale istruzione ha causato il primo blocco che ha causato gli altri blocchi.

Modifica per aggiungere un commento da @MikeBlandford :

La colonna bloccata indica lo spid del processo di blocco. Puoi eseguire kill {spid} per risolverlo.


7
La colonna bloccata indica lo spid del processo di blocco. Puoi eseguire kill {spid} per risolverlo.
Mike Blandford,

52

È possibile trovare i blocchi correnti sulla tabella seguendo la query.

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');

Vedi sys.dm_tran_locks

Se esistono più istanze dello stesso request_owner_type , la colonna request_owner_id viene utilizzata per distinguere ciascuna istanza. Per le transazioni distribuite, le colonne request_owner_type e request_owner_guid mostreranno le diverse informazioni sull'entità.

Ad esempio, la Sessione S1 possiede un blocco condiviso su Table1; e la transazione T1, che è in esecuzione nella sessione S1, possiede anche un blocco condiviso su Table1. In questo caso, la colonna resource_description restituita da sys.dm_tran_locks mostrerà due istanze della stessa risorsa. La colonna request_owner_type mostrerà un'istanza come sessione e l'altra come transazione. Inoltre, la colonna resource_owner_id avrà valori diversi.


36

Uso una visualizzazione di gestione dinamica (DMV) per acquisire i blocchi, nonché object_id o partition_id dell'elemento bloccato.

(DEVE passare al database che si desidera osservare per ottenere 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;

Sto cercando di usare questa affermazione per scoprire gli oggetti che un processo sta aspettando. Riesco a vedere chiaramente una sessione in attesa di un'altra utilizzando sp_who2e in sys.dm_os_waiting_task(entrambi cercando di aggiornare la stessa tabella). Ma la tua dichiarazione non restituisce alcuna riga. Qualche idea?
a_horse_with_no_name

17

È inoltre possibile utilizzare la sp_who2procedura memorizzata integrata per ottenere i processi di blocco e blocco correnti su un'istanza di SQL Server. In genere questo viene eseguito insieme a un'istanza di SQL Profiler per trovare un processo di blocco e esaminare il comando più recente emesso nel profiler.


5

Puoi trovare i dettagli tramite lo script seguente.

-- 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');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.