SP para analizar bloqueos en la BBDD, crear este SP en Master.
Para llamar al SP «sp_who2 active», podemos revisar los bloqueos ejecutando «dbcc inputbuffer(SPID)»
USE [master] GO /****** Object: StoredProcedure [sys].[sp_who2] Script Date: 11/21/2017 09:21:50 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER procedure [sys].[sp_who2] --- 1995/11/03 10:16 @loginame sysname = NULL as set nocount on declare @retcode int declare @sidlow varbinary(85) ,@sidhigh varbinary(85) ,@sid1 varbinary(85) ,@spidlow int ,@spidhigh int declare @charMaxLenLoginName varchar(6) ,@charMaxLenDBName varchar(6) ,@charMaxLenCPUTime varchar(10) ,@charMaxLenDiskIO varchar(10) ,@charMaxLenHostName varchar(10) ,@charMaxLenProgramName varchar(10) ,@charMaxLenLastBatch varchar(10) ,@charMaxLenCommand varchar(10) declare @charsidlow varchar(85) ,@charsidhigh varchar(85) ,@charspidlow varchar(11) ,@charspidhigh varchar(11) -- defaults select @retcode = 0 -- 0=good ,1=bad. select @sidlow = convert(varbinary(85), (replicate(char(0), 85))) select @sidhigh = convert(varbinary(85), (replicate(char(1), 85))) select @spidlow = 0 ,@spidhigh = 32767 -------------------------------------------------------------- IF (@loginame IS NULL) --Simple default to all LoginNames. GOTO LABEL_17PARM1EDITED -- select @sid1 = suser_sid(@loginame) select @sid1 = null if exists(select * from sys.syslogins where loginname = @loginame) select @sid1 = sid from sys.syslogins where loginname = @loginame IF (@sid1 IS NOT NULL) --Parm is a recognized login name. begin select @sidlow = suser_sid(@loginame) ,@sidhigh = suser_sid(@loginame) GOTO LABEL_17PARM1EDITED end -------- IF (lower(@loginame collate Latin1_General_CI_AS) IN ('active')) --Special action, not sleeping. begin select @loginame = lower(@loginame collate Latin1_General_CI_AS) GOTO LABEL_17PARM1EDITED end -------- IF (patindex ('%[^0-9]%' , isnull(@loginame,'z')) = 0) --Is a number. begin select @spidlow = convert(int, @loginame) ,@spidhigh = convert(int, @loginame) GOTO LABEL_17PARM1EDITED end -------- raiserror(15007,-1,-1,@loginame) select @retcode = 1 GOTO LABEL_86RETURN LABEL_17PARM1EDITED: -------------------- Capture consistent sysprocesses. ------------------- select spid ,status ,sid ,hostname ,program_name ,cmd ,cpu ,physical_io ,blocked ,dbid ,convert(sysname, rtrim(loginame)) as loginname ,spid as 'spid_sort' , substring( convert(varchar,last_batch,111) ,6 ,5 ) + ' ' + substring( convert(varchar,last_batch,113) ,13 ,8 ) as 'last_batch_char' ,request_id into #tb1_sysprocesses from sys.sysprocesses_ex with (nolock) if @@error <> 0 begin select @retcode = @@error GOTO LABEL_86RETURN end --------Screen out any rows? if (@loginame in ('active')) delete #tb1_sysprocesses where lower(status) = 'sleeping' and upper(cmd) in ( 'AWAITING COMMAND' ,'LAZY WRITER' ,'CHECKPOINT SLEEP' ) and blocked = 0 --------Prepare to dynamically optimize column widths. select @charsidlow = convert(varchar(85),@sidlow) ,@charsidhigh = convert(varchar(85),@sidhigh) ,@charspidlow = convert(varchar,@spidlow) ,@charspidhigh = convert(varchar,@spidhigh) select @charMaxLenLoginName = convert( varchar ,isnull( max( datalength(loginname)) ,5) ) ,@charMaxLenDBName = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),db_name(dbid))))) ,6) ) ,@charMaxLenCPUTime = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),cpu)))) ,7) ) ,@charMaxLenDiskIO = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),physical_io)))) ,6) ) ,@charMaxLenCommand = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),cmd)))) ,7) ) ,@charMaxLenHostName = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),hostname)))) ,8) ) ,@charMaxLenProgramName = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),program_name)))) ,11) ) ,@charMaxLenLastBatch = convert( varchar ,isnull( max( datalength( rtrim(convert(varchar(128),last_batch_char)))) ,9) ) from #tb1_sysprocesses where spid >= @spidlow and spid <= @spidhigh --------Output the report. EXEC( ' SET nocount off SELECT SPID = convert(char(5),spid) ,Status = CASE lower(status) When ''sleeping'' Then lower(status) Else upper(status) END ,Login = substring(loginname,1,' + @charMaxLenLoginName + ') ,HostName = CASE hostname When Null Then '' .'' When '' '' Then '' .'' Else substring(hostname,1,' + @charMaxLenHostName + ') END ,BlkBy = CASE isnull(convert(char(5),blocked),''0'') When ''0'' Then '' .'' Else isnull(convert(char(5),blocked),''0'') END ,DBName = substring(case when dbid = 0 then null when dbid <> 0 then db_name(dbid) end,1,' + @charMaxLenDBName + ') ,Command = substring(cmd,1,' + @charMaxLenCommand + ') ,CPUTime = substring(convert(varchar,cpu),1,' + @charMaxLenCPUTime + ') ,DiskIO = substring(convert(varchar,physical_io),1,' + @charMaxLenDiskIO + ') ,LastBatch = substring(last_batch_char,1,' + @charMaxLenLastBatch + ') ,ProgramName = substring(program_name,1,' + @charMaxLenProgramName + ') ,SPID = convert(char(5),spid) --Handy extra for right-scrolling users. ,REQUESTID = convert(char(5),request_id) from #tb1_sysprocesses --Usually DB qualification is needed in exec(). where spid >= ' + @charspidlow + ' and spid <= ' + @charspidhigh + ' -- (Seems always auto sorted.) order by spid_sort SET nocount on ' ) LABEL_86RETURN: if (object_id('tempdb..#tb1_sysprocesses') is not null) drop table #tb1_sysprocesses return @retcode -- sp_who2
SP_WHO3, igual que sp_who2, pero con detalle de querrys y mas info (añadir el SP a programability en la BBDD master) :
USE [Master] GO /****** Object: StoredProcedure [dbo].[sp_who3] Script Date: 11/21/2017 09:36:59 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[sp_who3] (@loginame Sysname = NULL) As Set NoCount On -- Variables Declare @retcode Int Declare @spidlow Int, @spidhigh Int Declare @charMaxLenLoginName Varchar(6), @charMaxLenDBName Varchar(6), @charMaxLenCPUTime Varchar(10), @charMaxLenDiskIO Varchar(10), @charMaxLenHostName Varchar(10), @charMaxLenProgramName Varchar(10), @charMaxLenLastBatch Varchar(10), @charMaxLenLastBatchDuration Varchar(10), @charMaxLenCommand Varchar(10) Declare @charsidlow Varchar(85), @charsidhigh Varchar(85), @charspidlow Varchar(11), @charspidhigh Varchar(11) -- Valores default Select @retcode = 0 -- 0=good ,1=bad. Select @spidlow = 0, @spidhigh = 32767 /* Parte donde se analiza la entrada y se acomodan los parametros */ -- Caso default, no recibi parametro @loginame If (@loginame Is NULL) Goto Label_Main -- Caso en que lo que recibi es un loginname If Exists(Select * From sys.syslogins Where loginname = @loginame) Goto Label_Main -- En caso de recibir el parametro en 'activo' le acomodo el collation If (Lower(@loginame Collate Latin1_General_CI_AS) In ('active')) --Special action, not sleeping. Begin Select @loginame = Lower(@loginame Collate Latin1_General_CI_AS) Goto Label_Main End -- Caso en que lo que recibi es un numero de pid If (patindex ('%[^0-9]%' , isNull(@loginame,'z')) = 0) Begin Select @spidlow = Convert(Int, @loginame), @spidhigh = Convert(Int, @loginame) Goto Label_Main End -- Si llegue hasta aca es porque hubo algun error RaisError(15007, -1, -1, @loginame) Select @retcode = 1 Goto Label_End /* Parte principal donde se obtienen y acomodan los datos de los procesos */ Label_Main: -- Creo la tabla temporal donde voy a guardar los procesos Create Table #TempProcesos ( spid Smallint, status NChar(30), sid Binary(86), hostname NChar(128), program_name NChar(128), cmd NChar(16), cpu Int, physical_io Bigint, blocked Smallint, dbid Smallint, loginname Sysname, spid_sort Smallint, last_batch_char Varchar(50), last_batch_duration Varchar(50), request_id Int, running_query Varchar(Max), blocking_query Varchar(Max) ) -- Meto en la tabla los procesos consultando la sysprocesses Insert Into #TempProcesos ( spid, status, sid, hostname, program_name, cmd, cpu, physical_io, blocked, dbid, loginname, spid_sort, last_batch_char, last_batch_duration, request_id ) Select spid, status, sid, hostname, program_name, cmd, cpu, physical_io, blocked, dbid, Convert(sysname, RTrim(loginame)), spid, SubString(Convert(Varchar, last_batch, 111), 6, 5) + ' ' + SubString(Convert(Varchar, last_batch, 113), 13, 8), Convert(Varchar(8), DateAdd(Second, DateDiff(Second, last_batch, GetDate()), 0), 114), request_id From sys.sysprocesses (Nolock) -- Si hay errores no sigo If @@error <> 0 Begin Select @retcode = @@error Goto Label_End End -- Si el parametro recibido es 'active' borro de la tabla temporal a todos los que esten inactivos If (@loginame In ('active')) Delete #TempProcesos Where Lower(status) = 'sleeping' And Upper(cmd) In ('AWAITING COMMAND', 'LAZY WRITER', 'CHECKPOINT SLEEP') And blocked = 0 -- Obtengo las querys usando un cursor que recorre todos los procesos y ejecuta un dbcc inputbuffer Declare @CurrentSpid Int, @GetQuery NVarchar(Max) Create Table #TempQuerys ( spid Int, EventType nvarchar(30), Parameters int, EventInfo nvarchar(Max) ) Declare #CursorProcesos Cursor For Select spid From #TempProcesos (Nolock) Open #CursorProcesos Fetch Next From #CursorProcesos Into @CurrentSpid While @@FETCH_STATUS = 0 Begin -- Agrego bloque try/catch porque puede no existir el PID si justo se termino la ejeucion Begin Try -- Ejecuto un dbcc inputbuffer para obtener la query asociada al spid Set @GetQuery = N'DBCC INPUTBUFFER(' + Convert(Varchar(255), @CurrentSpid) +') WITH NO_INFOMSGS' Insert Into #TempQuerys (EventType, Parameters, EventInfo) Exec sp_ExecuteSql @GetQuery Update #TempQuerys Set spid = @CurrentSpid Where spid Is NULL End Try Begin Catch -- Si hubo algun error borro el registro que puede habe quedado a medio insertar Delete From #TempQuerys Where spid Is NULL End Catch Fetch Next From #CursorProcesos Into @CurrentSpid End Close #CursorProcesos Deallocate #CursorProcesos -- Agrego las querys asociadas a cada PID, en el caso que tengan Update #TempProcesos Set running_query = Q.EventInfo From #TempProcesos P (Nolock) Join #TempQuerys Q (Nolock) On P.spid = Q.spid And Q.EventInfo Is Not NULL -- Agrego las querys asociadas a los procesos que bloquean, en el caso que existan Update #TempProcesos Set blocking_query = Q.EventInfo From #TempProcesos P (Nolock) Join #TempQuerys Q (Nolock) On P.blocked = Q.spid And P.blocked Is Not NULL And Q.EventInfo Is Not NULL -- Convierto los maximo y minimo spid a varchar para usarlo en le query Select @charspidlow = Convert(Varchar, @spidlow), @charspidhigh = Convert(Varchar, @spidhigh) -- Obtengo los maximos de cada campo para ajustar el tamaño de las columnas Select @charMaxLenLoginName = Convert(Varchar ,isNull(Max(Datalength(loginname)), 5) ), @charMaxLenDBName = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), db_name(dbid))))), 6) ), @charMaxLenCPUTime = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), cpu)))), 7) ), @charMaxLenDiskIO = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), physical_io)))), 6) ), @charMaxLenCommand = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), cmd)))), 7) ), @charMaxLenHostName = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), hostname)))), 8) ), @charMaxLenProgramName = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), program_name)))), 11) ), @charMaxLenLastBatch = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), last_batch_char)))), 9) ), @charMaxLenLastBatchDuration = Convert(Varchar ,isNull(Max(Datalength(RTrim(Convert(Varchar(128), last_batch_duration)))), 6) ) From #TempProcesos (Nolock) Where spid >= @spidlow And spid <= @spidhigh /* Parte donde armo la query completa de salida y la ejecuto */ Exec(' Set NoCount On Select SPID = Convert(Char(5),spid), Status = Case lower(status) When ''sleeping'' Then lower(status) Else upper(status) End, Login = SubString(loginname,1,' + @charMaxLenLoginName + '), HostName = Case hostname When NULL Then '' .'' When '' '' Then '' .'' Else SubString(hostname,1,' + @charMaxLenHostName + ') End, BlkBy = Case isNull(Convert(Char(5),blocked),''0'') When ''0'' Then '' .'' Else isNull(Convert(Char(5),blocked),''0'') End, DBName = SubString( Case When dbid = 0 Then NULL When dbid <> 0 Then db_name(dbid) End, 1,' + @charMaxLenDBName + '), Command = SubString(cmd,1,' + @charMaxLenCommand + '), CPUTime = SubString(Convert(varchar,cpu),1,' + @charMaxLenCPUTime + '), DiskIO = SubString(Convert(varchar,physical_io),1,' + @charMaxLenDiskIO + '), LastBatch = SubString(last_batch_char,1,' + @charMaxLenLastBatch + '), LastBatchDuration = SubString(last_batch_duration,1,' + @charMaxLenLastBatchDuration + '), ProgramName = SubString(program_name,1,' + @charMaxLenProgramName + '), RunningQuery = running_query, BlockingQuery = blocking_query From #TempProcesos Where spid >= ' + @charspidlow + ' And spid <= ' + @charspidhigh + ' Order By Convert(Int, spid) Set NoCount Off ') Label_End: -- Al final destruyo la tablas temporales si existen If (Object_id('tempdb..#TempQuerys') Is Not NULL) Drop Table #TempQuerys If (Object_id('tempdb..#TempProcesos') Is Not NULL) Drop Table #TempProcesos Set NoCount Off Return @retcode