Cómo verificar qué cerraduras hay en una mesa

158

¿Cómo podemos verificar qué bloqueos de la base de datos se aplican en qué filas en un lote de consulta?

¿Alguna herramienta que resalte el bloqueo de nivel de fila de la tabla en tiempo real?

DB: SQL Server 2005

Usman Shaheen
fuente

Respuestas:

118

Para agregar a las otras respuestas, sp_locktambién se puede usar para volcar la información de bloqueo completo en todos los procesos en ejecución. El resultado puede ser abrumador, pero si desea saber exactamente qué está bloqueado, es valioso ejecutarlo. Por lo general, lo uso junto con sp_who2para concentrarse rápidamente en los problemas de bloqueo.

Existen múltiples versiones diferentes de sp_lockprocedimientos "más amigables" disponibles en línea, dependiendo de la versión de SQL Server en cuestión.

En su caso, para SQL Server 2005, sp_locktodavía está disponible, pero en desuso, por lo que ahora se recomienda usar la sys.dm_tran_locksvista para este tipo de cosas. Puede encontrar un ejemplo de cómo "rodar su propia" función sp_lock aquí .

mwigdahl
fuente
116

Esto no le muestra exactamente qué filas están bloqueadas, pero esto puede serle útil.

Puede verificar qué declaraciones están bloqueadas ejecutando esto:

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

También le dirá qué espera cada bloque. Por lo tanto, puede rastrearlo hasta arriba para ver qué enunciado causó el primer bloque que causó los otros bloques.

Edite para agregar comentarios de @MikeBlandford :

La columna bloqueada indica el spid del proceso de bloqueo. Puede ejecutar kill {spid} para arreglarlo.

Brian R. Bondy
fuente
77
La columna bloqueada indica el spid del proceso de bloqueo. Puede ejecutar kill {spid} para arreglarlo.
Mike Blandford
52

Puede encontrar bloqueos actuales en su tabla siguiendo la 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');

Ver sys.dm_tran_locks

Si existen varias instancias del mismo tipo request_owner_type , la columna request_owner_id se usa para distinguir cada instancia. Para transacciones distribuidas, request_owner_type y request_owner_guid columnas mostrarán la información de la entidad diferente.

Por ejemplo, la sesión S1 posee un bloqueo compartido en Table1; y la transacción T1, que se ejecuta en la sesión S1, también posee un bloqueo compartido en la Tabla1. En este caso, la columna resource_description que devuelve sys.dm_tran_locks mostrará dos instancias del mismo recurso. La columna request_owner_type mostrará una instancia como sesión y la otra como transacción. Además, la columna resource_owner_id tendrá valores diferentes.

Somnath Muluk
fuente
36

Utilizo una Vista de gestión dinámica (DMV) para capturar bloqueos, así como el object_id o la parte de partición del elemento que está bloqueado.

(DEBE cambiar a la base de datos que desea observar para obtener 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
fuente
Estoy tratando de usar esta declaración para descubrir los objetos que un proceso está esperando. Puedo ver claramente una sesión esperando otra usando sp_who2y en sys.dm_os_waiting_task(ambos tratando de actualizar la misma tabla). Pero su declaración no devuelve ninguna fila. ¿Algunas ideas?
a_horse_with_no_name
17

También puede usar el sp_who2procedimiento almacenado incorporado para obtener procesos bloqueados y bloqueantes actuales en una instancia de SQL Server. Por lo general, ejecuta esto junto con una instancia de SQL Profiler para encontrar un proceso de bloqueo y ver el comando más reciente que spid emitió en profiler.

Neil Barnwell
fuente
5

Puede encontrar detalles a través del siguiente script.

-- 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
fuente