¿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
¿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
Respuestas:
Para agregar a las otras respuestas, sp_lock
tambié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_who2
para concentrarse rápidamente en los problemas de bloqueo.
Existen múltiples versiones diferentes de sp_lock
procedimientos "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_lock
todavía está disponible, pero en desuso, por lo que ahora se recomienda usar la sys.dm_tran_locks
vista para este tipo de cosas. Puede encontrar un ejemplo de cómo "rodar su propia" función sp_lock aquí .
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.
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');
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.
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;
sp_who2
y en sys.dm_os_waiting_task
(ambos tratando de actualizar la misma tabla). Pero su declaración no devuelve ninguna fila. ¿Algunas ideas?
También puede usar el sp_who2
procedimiento 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.
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');