top of page
Foto do escritorCloudDB

SQL Server - Monitora Lock - Cria Procedure, Tabela E Job - Inclui A Consulta

Esse script cria uma tabela de monitoração de locks e de waits bem como uma stored procedure para coletar esses dados no SQL Server e um job schedulado para captura de histórico da consulta.


É excelente para voce entender a causa raiz do problema de performance.


-- SCRIPT PARA CRIAÇÃO DE PROCEDURE, TABELA E JOB PARA MONITORAMENTO DE BLOQUEIOS



/****** CRIAÇÃO DE PROCEDURE SP MONITORAMENTO LOCKS ******/

use msdb

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO


CREATE PROCEDURE [dbo].[sp_MonitoramentoLocks]

as


DECLARE @tempo INT = 1000 --miliseg

declare @idlog varchar(128) = newid()

declare @tab table (

[session_id] [smallint] NOT NULL,

[blocked_by] [smallint] NOT NULL,

[login] [nchar](128) NOT NULL,

[host_name] [nchar](128) NOT NULL,

[program_name] [nchar](128) NOT NULL,

[Query] [nvarchar](max) NULL,

[Command] [nchar](16) NOT NULL,

[database] [sysname] NOT NULL,

[last_wait_type] [nchar](32) NOT NULL,

[wait_time_sec] [bigint] NULL,

[last_batch] [datetime] NOT NULL,

[login_time] [datetime] NOT NULL,

[status] [nchar](30) NOT NULL,

[cpu] [int] NULL,

[capture_time] [datetime] NOT NULL,

[ID_log] [uniqueidentifier] NULL)


insert into @tab


Select

SPRO.spid AS [session_id]

,SPRO.blocked AS [blocked_by]

,SPRO.loginame AS [login]

,SPRO.hostname AS [host_name]

--,SPRO.program_name AS [program_name1]

,CASE WHEN LTRIM(RTRIM(SPRO.[Program_name])) LIKE '%TSQL Job%' THEN B.NAME

ELSE LTRIM(RTRIM(SPRO.[Program_name])) END AS [Program_name]

,CASE WHEN Text LIKE 'FETCH API_CURSOR%'

THEN (SELECT TOP 1 c.properties +' | '+ t.text

FROM sys.dm_exec_cursors (SPRO.spid) c

CROSS APPLY sys.dm_exec_sql_text (c.sql_handle) t )

ELSE Text END AS [Query]

--,Text AS [Query]

,SPRO.cmd AS [Command]

,DTBS.name AS [database]

,SPRO.lastwaittype AS [last_wait_type]

,SPRO.waittime/1000 AS [wait_time]

,SPRO.last_batch AS [last_batch]

,SPRO.login_time AS [login_time]

,SPRO.status AS [status]

,(SPRO.cpu/1000) AS [cpu]

,getdate() AS [capture_time]

,@idlog AS [ID_log]



FROM sys.sysprocesses AS SPRO

CROSS APPLY sys.dm_exec_sql_text(sql_handle)

OUTER APPLY (SELECT NAME FROM MSDB..SYSJOBS (NOLOCK)

WHERE '0x'+CONVERT(char(32),CAST(job_id AS binary(16)),2) = SUBSTRING(SPRO.[Program_name],30,34)) B

INNER JOIN sys.databases AS DTBS

ON SPRO.dbid = DTBS.database_id

where lastwaittype <> 'miscellaneous'

and SPRO.spid >0

and SPRO.blocked <> 0

and SPRO.waittime >@tempo




/****** INSERE OS DADOS NA TABELA LOG_LOCKS ******/


INSERT INTO MSDB.dbo.log_locks




select * from @tab

union


Select

SPRO.spid AS [session_id]

,SPRO.blocked AS [blocked_by]

,SPRO.loginame AS [login]

,SPRO.hostname AS [host_name]

--,SPRO.program_name AS [program_name]

,CASE WHEN LTRIM(RTRIM(SPRO.[Program_name])) LIKE '%TSQL Job%' THEN B.NAME

ELSE LTRIM(RTRIM(SPRO.[Program_name])) END AS [Program_name]

,CASE WHEN Text LIKE 'FETCH API_CURSOR%'

THEN (SELECT TOP 1 c.properties +' | '+ t.text

FROM sys.dm_exec_cursors (SPRO.spid) c

CROSS APPLY sys.dm_exec_sql_text (c.sql_handle) t )

ELSE Text END AS [Query]

--,Text AS [Query]

,SPRO.cmd AS [Command]

,DTBS.name AS [database]

,SPRO.lastwaittype AS [last_wait_type]

,SPRO.waittime/1000 AS [wait_time]

,SPRO.last_batch AS [last_batch]

,SPRO.login_time AS [login_time]

,SPRO.status AS [status]

,(SPRO.cpu/1000) AS [cpu]

,getdate() AS [capture_time]

,@idlog AS [ID_log]




FROM sys.sysprocesses AS SPRO

CROSS APPLY sys.dm_exec_sql_text(sql_handle)

OUTER APPLY (SELECT NAME FROM MSDB..SYSJOBS (NOLOCK)

WHERE '0x'+CONVERT(char(32),CAST(job_id AS binary(16)),2) = SUBSTRING(SPRO.[Program_name],30,34)) B

INNER JOIN sys.databases AS DTBS

ON SPRO.dbid = DTBS.database_id

where SPRO.spid in (select blocked_by from @tab)

go

/****** CRIA A TABELA LOG_LOCKS ******/

SET ANSI_NULLS ON

GO


SET QUOTED_IDENTIFIER ON

GO


CREATE TABLE [dbo].[log_locks](

[session_id] [smallint] NOT NULL,

[blocked_by] [smallint] NOT NULL,

[login] [nchar](128) NOT NULL,

[host_name] [nchar](128) NOT NULL,

[program_name] [nchar](128) NOT NULL,

[Query] [nvarchar](max) NULL,

[Command] [nchar](16) NOT NULL,

[database] [sysname] NOT NULL,

[last_wait_type] [nchar](32) NOT NULL,

[wait_time_sec] [bigint] NULL,

[last_batch] [datetime] NOT NULL,

[login_time] [datetime] NOT NULL,

[status] [nchar](30) NOT NULL,

[cpu] [int] NULL,

[capture_time] [datetime] NOT NULL,

[ID_log] [uniqueidentifier] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO



/****** CRIACAO DE JOB DBA - MONITORA LOCK ******/


USE [msdb]

GO



BEGIN TRANSACTION

DECLARE @ReturnCode INT

SELECT @ReturnCode = 0

IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)

BEGIN

EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback


END


DECLARE @jobId BINARY(16)

EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'DBA - Monitora Lock',

@enabled=1,

@notify_level_eventlog=0,

@notify_level_email=0,

@notify_level_netsend=0,

@notify_level_page=0,

@delete_level=0,

@description=N'No description available.',

@category_name=N'[Uncategorized (Local)]',

@owner_login_name=N'sa', @job_id = @jobId OUTPUT

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'.',

@step_id=1,

@cmdexec_success_code=0,

@on_success_action=1,

@on_success_step_id=0,

@on_fail_action=2,

@on_fail_step_id=0,

@retry_attempts=0,

@retry_interval=0,

@os_run_priority=0, @subsystem=N'TSQL',

@command=N'EXEC [dbo].[SP_MonitoramentoLocks]

',

@database_name=N'msdb',

@flags=0

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'.',

@enabled=1,

@freq_type=4,

@freq_interval=1,

@freq_subday_type=2,

@freq_subday_interval=10,

@freq_relative_interval=0,

@freq_recurrence_factor=0,

@active_start_date=20200108,

@active_end_date=99991231,

@active_start_time=0,

@active_end_time=235959,

@schedule_uid=N'34a970a7-8ad8-4aef-8919-11020b25815d'

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

COMMIT TRANSACTION

GOTO EndSave

QuitWithRollback:

IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION

EndSave:

GO



--------------------------------------------------------------------------------------------


-- APÓS TER TUDO CRIADO, DEVE-SE USAR O SCRIPT ABAIXO PARA FAZER A CONSULTA DE BLOQUEIOS


/****** SCRIPT PARA CONSULTA NA TABELA LOG_LOCKS ******/



SELECT TOP (1000) [session_id] "ID Bloqueado"

,[blocked_by] "ID Bloqueando"

,[login] "Login"

,[host_name] "Host"

,[wait_time_sec] "Tempo de espera"

,[program_name] "Programa"

,[Query] "Query"

,[Command] "Comando"

,[database] "Banco"

,[capture_time] "Data e hora de captura"

,[last_batch] "Data e hora que rodou por último"

,[login_time] "Data e hora de login"

,[status] "Status"

,[cpu] "CPU"

,[last_wait_type] "Último tipo de espera"

,[ID_log] "ID Log"

FROM msdb.[dbo].[log_locks]

-- where [wait_time_sec] > 10

order by capture_time desc

1.060 visualizações1 comentário

Posts recentes

Ver tudo

1 Comment


Fernanda Araujo
Fernanda Araujo
Mar 17, 2023

Implementei o job com algumas adaptações e o monitoramento de locks por hora está rodando direitinho. Obrigada!

Like
bottom of page