当前位置:网站首页>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 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
Let's make a test example to verify
1: Open the first session window 1, Execute the following statement
USE DBMonitor;
GO
BEGIN TRANSACTION
SELECT * FROM dbo.TEST(TABLOCKX);
--COMMIT TRANSACTION;
2: Open the second session window 2, Execute the following statement
USE DBMonitor;
GO
SELECT * FROM dbo.TEST
3: 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 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
As 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]
GO
IF NOT EXISTS(SELECT * FROM sys.objects WHERE object_id=OBJECT_ID(N'[Maint].[BlockingSQLHistory]') AND type='U')
BEGIN
CREATE 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)
)
END
GO
The stored procedure is as follows :
USE [YourSQLDba]
GO
IF 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]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--==================================================================================================================
-- 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
)
AS
BEGIN
SET 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
END
END
GO
Finally, 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 qt
WHERE 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
边栏推荐
- DOM//
- 【js学习笔记五十四】BFC方式
- BOM//
- 到底谁才是“良心”国产品牌?
- Solution of ellipsis when pytorch outputs tensor (output tensor completely)
- Node の MongoDB Driver
- 非技術部門,如何參與 DevOps?
- 2022年危险化学品经营单位主要负责人特种作业证考试题库及答案
- 小红书自研KV存储架构如何实现万亿量级存储与跨云多活
- In the year of "mutual entanglement" of mobile phone manufacturers, the "machine sea tactics" failed, and the "slow pace" playing method rose
猜你喜欢
Apple 5g chip research and development failure? It's too early to get rid of Qualcomm
非技術部門,如何參與 DevOps?
AD20 制作 Logo
第五届 Polkadot Hackathon 创业大赛全程回顾,获胜项目揭秘!
LSTM应用于MNIST数据集分类(与CNN做对比)
Learning notes 5 - high precision map solution
非技术部门,如何参与 DevOps?
What is the most suitable book for programmers to engage in open source?
风控模型启用前的最后一道工序,80%的童鞋在这都踩坑
Workmanager Learning one
随机推荐
Go语言-1-开发环境配置
SLAM 01.人类识别环境&路径的模型建立
Customize the left sliding button in the line in the applet, which is similar to the QQ and Wx message interface
【DNS】“Can‘t resolve host“ as non-root user, but works fine as root
How can non-technical departments participate in Devops?
埋点111
Go-2-Vim IDE常用功能
[dark horse morning post] Luo Yonghao responded to ridicule Oriental selection; Dong Qing's husband Mi Chunlei was executed for more than 700million; Geely officially acquired Meizu; Huawei releases M
WorkManager的学习二
The most complete is an I2C summary
Solution of ellipsis when pytorch outputs tensor (output tensor completely)
手机厂商“互卷”之年:“机海战术”失灵,“慢节奏”打法崛起
AtCoder Beginner Contest 258「ABCDEFG」
Golang应用专题 - channel
【Vite】1371- 手把手开发 Vite 插件
2022年T电梯修理操作证考试题及答案
脚手架开发进阶
爬虫(9) - Scrapy框架(1) | Scrapy 异步网络爬虫框架
@Serializedname annotation use
字符串、、