当前位置:网站首页>SQL Server monitoring statistics blocking script information
SQL Server monitoring statistics blocking script information
2022-07-05 10:39:00 【Full stack programmer webmaster】
The database is blocked (Blocking) The essence of :SQL Statement continuously holds the lock for too long , Too many , It's too big . Blocking is a side effect of transaction isolation , It's inevitable , And it's a common phenomenon in database system . But the time and frequency of blocking should be controlled within a certain range , Blocking lasts too long or blocking occurs too much ( all too often ), It will have a serious impact on the performance of the database .
A lot of times ,DBA You need to know when the database has performance problems , Is there any blockage ? When did it start ? Happened on that database ? Blocking occurs in those SQL Between sentences ? How long is the jam ? The frequency of congestion ? Blocking related connections are sent from those client applications ?…….
If we can know these specific information , We can quickly locate the problem , Analyze the cause of blocking , So as to find out the root cause of performance problems , And give the corresponding solutions according to the specific reasons ( Index adjustment 、 Optimize SQL Statement etc. ).
There are many ways to check blocking , I am in this blog MS SQL Common scripts for daily maintenance and management ( Two ) There are some ways to check the blocking :
Method 1: Check that caused the blockage , see blk Not for 0 The record of , If there is a blocking process , Is the session of the blocking process ID. Otherwise, the column is zero .
EXEC sp_who active
Method 2: Check that caused the blockage , View fields BlkBy, This can be compared with sp_who More information .
EXEC sp_who2 active
Method 3:sp_lock System stored procedure , Report information about locks , But it is inconvenient to locate the problem
Method 4:sp_who_lock stored procedure
Method 5: Right click on the server - choice “ Activities and monitors ”, View process options . Be careful “ Task status ” Field .
Method 6: Right click the service name - Select Report - Standard report - Activities - All blocking transactions .
But the above method , For example sp_who、 sp_who2,sp_who_lock etc. , Have more or less shortcomings : For example, you cannot view blocked and blocked SQL sentence . You can't check the situation of blocking in a period of time ; The blocking time is not displayed ……. We want to realize the following functions :
1: Checking that session blocked that session
2: Blocked sessions and blocked sessions are executing SQL sentence
3: How long has it been blocked
4: Like client IP、Proagram_Name Information like that
5: The point in time when blocking occurs
6: The frequency of congestion
7: if necessary , Relevant developers should be informed ,DBA You can't do everything, can you , Then I'll die of fatigue , Developers have to be involved to optimize ( Some problems should be solved by them ), Learn more about the specific operation of the system , It helps them understand the problem 、 solve the problem .
8: Turn on this function when necessary , There is no need to turn off this function
So in order to meet the above functions , With the following SQL sentence
SELECT wt.blocking_session_id AS BlockingSessesionId ,sp.program_name AS ProgramName ,COALESCE(sp.LOGINAME, sp.nt_username) AS HostName ,ec1.client_net_address AS ClientIpAddress ,db.name AS DatabaseName ,wt.wait_type AS WaitType ,ec1.connect_time AS BlockingStartTime ,wt.WAIT_DURATION_MS/1000 AS WaitDuration ,ec1.session_id AS BlockedSessionId ,h1.TEXT AS BlockedSQLText ,h2.TEXT AS BlockingSQLTextFROM sys.dm_tran_locks AS tlINNER JOIN sys.databases db ON db.database_id = tl.resource_database_idINNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_addressINNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_idINNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_idLEFT OUTER JOIN master.dbo.sysprocesses sp ON SP.spid = wt.blocking_session_idCROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2Let's make a test example to verify
1: Open the first session window 1, Execute the following statement
USE DBMonitor;GOBEGIN TRANSACTIONSELECT * FROM dbo.TEST(TABLOCKX);--COMMIT TRANSACTION;2: Open the second session window 2, Execute the following statement
USE DBMonitor;GOSELECT * FROM dbo.TEST3: Open the third session window 3, Execute the following statement
SELECT wt.blocking_session_id AS BlockingSessesionId ,sp.program_name AS ProgramName ,COALESCE(sp.LOGINAME, sp.nt_username) AS HostName ,ec1.client_net_address AS ClientIpAddress ,db.name AS DatabaseName ,wt.wait_type AS WaitType ,ec1.connect_time AS BlockingStartTime ,wt.WAIT_DURATION_MS/1000 AS WaitDuration ,ec1.session_id AS BlockedSessionId ,h1.TEXT AS BlockedSQLText ,h2.TEXT AS BlockingSQLTextFROM sys.dm_tran_locks AS tlINNER JOIN sys.databases db ON db.database_id = tl.resource_database_idINNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_addressINNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_idINNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_idLEFT OUTER JOIN master.dbo.sysprocesses sp ON SP.spid = wt.blocking_session_idCROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2As shown below , We can see the information of blocking other sessions and blocked sessions , As shown below
Now up there SQL The function of viewing the specific information of blocking has been basically realized , But now there are several problems :
1: above SQL The script is only suitable for viewing blocking information when blocking has occurred , If there is no blockage , I can't just click and execute all the time , Because blocking may not happen at that time , It will only appear in a specific period of time .
2: I want to know about the blocking of the database in a period of time , Then you need to keep the blocking information .
3: Sometimes I'm too busy , I want to send these specific blocking information to relevant developers , Let them know the specific situation .
So I want to realize this function through a stored procedure , By setting parameters @OutType, The default is to output blocking session information , When the parameter is ”Table” when , Write blocking information to the database table , If the parameter is “Email” Indicates that the blocking information will be sent to the developer by mail .
It's just this time , I am here YourSQLDba Expand some functions on , So I put this stored procedure in YouSQLDba In the database .
USE [YourSQLDba]GOIF NOT EXISTS(SELECT * FROM sys.objects WHERE object_id=OBJECT_ID(N'[Maint].[BlockingSQLHistory]') AND type='U')BEGINCREATE TABLE Maint.BlockingSQLHistory( RecordTime DATETIME , DatabaseName SYSNAME , BlockingSessesionId SMALLINT , ProgramName NCHAR(128) , UserName NCHAR(256) , ClientIpAddress VARCHAR(48) , WaitType NCHAR(60) , BlockingStartTime DATETIME , WaitDuration BIGINT , BlockedSessionId INT , BlockedSQLText NVARCHAR(MAX) , BlockingSQLText NVARCHAR(MAX) , CONSTRAINT PK_BlockingSQLHistory PRIMARY KEY(RecordTime))ENDGOThe stored procedure is as follows :
USE [YourSQLDba]GOIF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Maint].[sp_who_blocking]') AND type in (N'P', N'PC'))DROP PROCEDURE [Maint].[sp_who_blocking]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO--==================================================================================================================-- ProcedureName : [Maint].[sp_who_blocking]-- Author : Kerry http://www.cnblogs.com/kerrycode/-- CreateDate : 2014-04-23-- Description : Monitor database blocking , Display blocking session information or collect blocking session information or send alarm email /****************************************************************************************************************** Parameters : Parameter description ******************************************************************************************************************** @OutType : The default is to output blocking session information ,"Table", "Email" Respectively, it means writing blocking information into the table or sending mail @EmailSubject : Email subject . The default is Sql Blocking Alert, General designation , for example “ServerName Sql Blocking Alert" @ProfileName : @profile_name The default value is YourSQLDba_EmailProfile @RecipientsLst : List of recipients ******************************************************************************************************************** Modified Date Modified User Version Modified Reason******************************************************************************************************************** 2014-04-23 Kerry V01.00.00 New stored procedure [Maint].[sp_who_blocking]*******************************************************************************************************************/--==================================================================================================================CREATE PROCEDURE [Maint].[sp_who_blocking]( @OutType VARCHAR(8) ='Default' , @EmailSubject VARCHAR(120)='Sql Blocking Alert' , @ProfileName sysname='YourSQLDba_EmailProfile' , @RecipientsLst VARCHAR(MAX) = NULL)ASBEGINSET NOCOUNT ON;DECLARE @HtmlContent NVARCHAR(MAX) ; IF @OutType NOT IN ('Default', 'Table','Email') BEGIN PRINT 'The parameter @OutType is not correct,please check it'; return; END IF @OutType ='Default' BEGIN SELECT db.name AS DatabaseName ,wt.blocking_session_id AS BlockingSessesionId ,sp.program_name AS ProgramName ,COALESCE(sp.LOGINAME, sp.nt_username) AS UserName ,ec1.client_net_address AS ClientIpAddress ,wt.wait_type AS WaitType ,ec1.connect_time AS BlockingStartTime ,wt.WAIT_DURATION_MS/1000 AS WaitDuration ,ec1.session_id AS BlockedSessionId ,h1.TEXT AS BlockedSQLText ,h2.TEXT AS BlockingSQLText FROM sys.dm_tran_locks AS tl INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id LEFT OUTER JOIN master.dbo.sysprocesses sp ON SP.spid = wt.blocking_session_id CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2; END ELSE IF @OutType='Table' BEGIN INSERT INTO [Maint].[BlockingSQLHistory] SELECT GETDATE() AS RecordTime ,db.name AS DatabaseName ,wt.blocking_session_id AS BlockingSessesionId ,sp.program_name AS ProgramName ,COALESCE(sp.LOGINAME, sp.nt_username) AS UserName ,ec1.client_net_address AS ClientIpAddress ,wt.wait_type AS WaitType ,ec1.connect_time AS BlockingStartTime ,wt.WAIT_DURATION_MS/1000 AS WaitDuration ,ec1.session_id AS BlockedSessionId ,h1.TEXT AS BlockedSQLText ,h2.TEXT AS BlockingSQLText FROM sys.dm_tran_locks AS tl INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id LEFT OUTER JOIN master.dbo.sysprocesses sp ON SP.spid = wt.blocking_session_id CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2; END ELSE IF @OutType='Email' BEGIN SET @HtmlContent = N'<head>' + N'<style type="text/css">h2, body {font-family: Arial, verdana;} table{font-size:11px; border-collapse:collapse;} td{background-color:#F1F1F1; border:1px solid black; padding:3px;} th{background-color:#99CCFF;}</style>' + N'<table border="1">' + N'<tr> <th>DatabaseName</th> <th>BlockingSessesionId</th> <th>ProgramName</th> <th>UserName</th> <th>ClientIpAddress</th> <th>WaitType</th> <th>BlockingStartTime</th> <th>WaitDuration</th> <th>BlockedSessionId</th> <th>BlockedSQLText</th> <th>BlockingSQLText</th> </tr>' + CAST ( (SELECT db.name AS TD, '' ,wt.blocking_session_id AS TD, '' ,sp.program_name AS TD, '' ,COALESCE(sp.LOGINAME, sp.nt_username) AS TD, '' ,ec1.client_net_address AS TD, '' ,wt.wait_type AS TD, '' ,ec1.connect_time AS TD, '' ,wt.WAIT_DURATION_MS/1000 AS TD, '' ,ec1.session_id AS TD, '' ,h1.TEXT AS TD, '' ,h2.TEXT AS TD, '' FROM sys.dm_tran_locks AS tl INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id LEFT OUTER JOIN master.dbo.sysprocesses sp ON SP.spid = wt.blocking_session_id CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 FOR XML PATH('tr'), TYPE ) AS NVARCHAR(MAX) ) + N'</table>' IF @HtmlContent IS NOT NULL BEGIN EXEC msdb.dbo.sp_send_dbmail @profile_name = @ProfileName , @recipients = @RecipientsLst , @subject = @EmailSubject , @body = @HtmlContent , @body_format = 'HTML' ; END ENDENDGOFinally, create a new job in the database , Call the stored procedure , Then enable the blocking of the job monitoring database for a certain period of time , The frequency of homework execution is a headache that is difficult to decide , The details should be determined according to the system , I'm used to it 2 Once per minute .
Last , There is another problem with this script , If blocked or blocked SQL A statement is a script in a stored procedure , According to the SQL Is the whole stored procedure , Instead of being implemented SQL sentence , At present, there is no good way to solve this problem . I am currently manually checking the congestion , If you have to check the blocked executing in the stored procedure SQL, Generally combined with the following SQL Statement view ( Enter blocked or blocked sessions ID replace @sessionid)
SELECT [Spid] = er.session_id ,[ecid] ,[Database] = DB_NAME(sp.dbid) ,[Start_Time] ,[SessionRunTime] = datediff(SECOND, start_time,getdate()) ,[SqlRunTime]= RIGHT(convert(varchar, dateadd(ms, datediff(ms, sp.last_batch, getdate()), '1900-01-01'), 121), 12) ,[HostName] ,[Users]=COALESCE(sp.LOGINAME, sp.nt_username) ,[Status] = er.status ,[WaitType] = er.wait_type ,[Waitime] = er.wait_time/1000 ,[Individual Query] = SUBSTRING(qt.text, er.statement_start_offset / 2, ( CASE WHEN er.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE er.statement_end_offset END - er.statement_start_offset ) / 2) ,[Parent Query] = qt.text ,[PROGRAM_NAME] = program_name FROM sys.dm_exec_requests er INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS qtWHERE session_Id = @sessionid;Publisher : Full stack programmer stack length , Reprint please indicate the source :https://javaforall.cn/109818.html Link to the original text :https://javaforall.cn
边栏推荐
- BOM//
- 括号匹配问题(STL)
- LSTM应用于MNIST数据集分类(与CNN做对比)
- 上拉加载原理
- Today in history: the first e-book came out; The inventor of magnetic stripe card was born; The pioneer of handheld computer was born
- In the year of "mutual entanglement" of mobile phone manufacturers, the "machine sea tactics" failed, and the "slow pace" playing method rose
- Events and bubbles in the applet of "wechat applet - Basics"
- php解决redis的缓存雪崩,缓存穿透,缓存击穿的问题
- 在C# 中实现上升沿,并模仿PLC环境验证 If 语句使用上升沿和不使用上升沿的不同
- [vite] 1371 - develop vite plug-ins by hand
猜你喜欢

谈谈对Flink框架中容错机制及状态的一致性的理解

微信核酸检测预约小程序系统毕业设计毕设(8)毕业设计论文模板

Learning Note 6 - satellite positioning technology (Part 1)

How to write high-quality code?

Pseudo class elements -- before and after

IDEA新建sprintboot项目

Events and bubbles in the applet of "wechat applet - Basics"

非技术部门,如何参与 DevOps?

Web3基金会「Grant计划」赋能开发者,盘点四大成功项目

【JS】提取字符串中的分数,汇总后算出平均分,并与每个分数比较,输出
随机推荐
iframe
Taro进阶
WorkManager学习一
到底谁才是“良心”国产品牌?
Implementation of wechat applet bottom loading and pull-down refresh
非技術部門,如何參與 DevOps?
在C# 中实现上升沿,并模仿PLC环境验证 If 语句使用上升沿和不使用上升沿的不同
How to plan the career of a programmer?
“军备竞赛”时期的对比学习
vscode的快捷键
第五届 Polkadot Hackathon 创业大赛全程回顾,获胜项目揭秘!
IDEA新建sprintboot项目
Web Components
小程序框架Taro
[可能没有默认的字体]Warning: imagettfbbox() [function.imagettfbbox]: Invalid font filename……
GO项目实战 — Gorm格式化时间字段
Go项目实战—参数绑定,类型转换
微信核酸检测预约小程序系统毕业设计毕设(7)中期检查报告
How to write high-quality code?
分享.NET 轻量级的ORM