Descubrir bloqueos en SQL Server

Posted by Miguel Egea | Posted in Relacional | Posted on 08-01-2010

4

Los bloqueos son la principal causa de bajo rendimiento inexplicable, y generalmente son muy complicados de cazar, de detectar y de solucionar, hablaremos de bloqueos más adelante, pero ahora mismo vamos a poner un procedimiento almacenado que sirve para cazar a los procesos bloqueadores y pondremos una imagen en la que se ve cual es el resultado, en proximos capítulos pondremos como configurar el SQL Mail para que además nos lleguen por correo electrónico

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
-- ***************************************************************************
-- Copyright (C) PortalSQL 2006
--
-- Fichero: CazaBloqueadores.sql
-- Descr.: Busca bloqueos que se mantengan
-- durante el tiempo que le pasemos por parámetro, si hay bloqueos que se mantienen
-- muestra información relevante
-- autor: Miguel Egea Gómez -- Solid Quality Learning IberoAmericana
--
-- comentarios: Puede ser adecuado meter ejecutar este procedimiento desde un job y
-- usar DatabaseMail para reportar sus resultados al administrador de base
-- de datos.
-- He usado la vista de compatibilidad sys.sysprocesses, esto es porque he c
-- comprobado que algunas ocasiones la tabla sys.dm_exec_request no tiene registros
-- para los bloqueadores.
--
-- Parámetros de entrada:
-- @waittime --> Tiempo que debe esperarse para considerar que hay un bloqueo
-- Valores de retorno : 0--> Funcionó de forma correcta
-- 1--> En cualquir otro caso
--
-- <!--(más reciente más arriba) -->
-- yyyy/mm/dd by description
-- ========== ======= ==========================================================
-- 2006/06/04 MEG Creación.
--
-- ***************************************************************************
-- Ejemplo de llamada
--
/*
DECLARE @Valor varchar(10) ,@result int
SET @Valor='00:00:02'
EXEC @result =CazaBloqueadores @valor
select @result</code>
 
*/ 
 
CREATE PROC CazaBloqueadores @waittime varchar(10)
as
begin
begin try
declare @t table (bloqueado int, bloqueador int)
-- usaremos la variable de tipo tabla para esperar
insert into @t (bloqueado,bloqueador)
select session_id, blocking_session_id
from sys.dm_exec_requests der
where blocking_session_id!=0
-- Recogemos los objetos que están bloqueados..
waitfor delay @waittime
SELECT der.session_id [Sesion bloqueada],
det.text [Comando Bloqueado],
der.[blocking_Session_id] [id del bloqueador],
subq.TEXT [Comando Bloqueador],
des.[host_name] [Nombre del host],
des.[Program_name] [Aplicación],
db_name(der.database_id) [Base de Datos],
user_name(der.user_id) [usuario de bbdd],
des.login_name [login],
cast(des.context_info as varchar(100)) [Informacion Adicional],
des.cpu_time [Tiempo de CPU],
des.total_elapsed_time [Tiempo de espera],
des.logical_reads [lecturas],
des.writes [escrituras],
der.start_time [Comenzó],
der.status [estado],
case des.transaction_isolation_level
when 0 then 'Sin especificar'
when 1 then 'Read Uncommitted'
when 2 then 'Read Committed'
when 3 then 'Repeatable reads'
when 4 then 'Serializable'
when 5 then 'Snapshot'
else 'Inesperado'
end [Nivel de Aislamiento]
FROM sys.dm_exec_requests der
INNER JOIN sys.dm_exec_sessions des
ON der.session_id=des.session_id
CROSS APPLY sys.dm_exec_sql_text(sql_handle) det
left join (select SPID session_id, det2.[text]
from sys.sysprocesses der2
CROSS APPLY sys.dm_exec_sql_text(sql_handle) det2
) subq on der.[blocking_Session_id]=subq.session_id
WHERE der.blocking_session_id
in (select bloqueador from @t)
return 0
end try
begin catch
declare @error sysname
set @error=ERROR_MESSAGE()
raiserror (@error,16,1)
return 1
end catch
end 

Aquí puedes ver una imagen en la que se ejecuta un comando que genera un bloqueo, y un comando que se ve bloqueado por ese bloqueo, cuando se crea una tabla dentro de una transacción se genera un bloqueo, un select que consulte esa tabla espera a que se haga commit o rollback en la creación, para devolver los registros o un error. 

a continuación puedes ver más resultados devueltos por el procedimiento almacenado

Disfruta del código