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

Comments (4)

Un consejo, instalate el plugin codebox para que sea mas entendible para todos nosotros tu codigo :D

Lo dicho eres una p… máquina. Interesantísimo como todos tus artículos. Por cierto, haber cuando nos deleitas con uno dedicado a directivas, ya sabes, por pedir que no quede :)

Nos vemos ….

Instalado el plugging, realmente instalado por segunda vez, porque lo instalé la primera y algo debió subirse mal, pensé que no funcionaba ya hora… me parece una maravilla, gracias GeekZero

Muchas gracias por el aporte. Espero que me sea de utilidad en algún momento, que seguro que así será.

Un saludo

Write a comment