如何监控和解决SQL Server的阻塞(2)(事件通知)

本文详述了如何监控SQL Server的阻塞问题,重点在于设定阻塞的厥值,并通过服务器配置选项blocked process threshold进行设置。当阻塞超过预设阈值时,通过事件通知发送包含阻塞信息的邮件给DBA。步骤包括创建事件通知、阻塞表、存储过程以及处理阻塞的队列。

 

上篇介绍了什么是阻赛,以及如何察看"当前"的阻塞现象. 这篇我们详细谈一下如何去监控阻塞.

 

1. 什么是阻塞的厥值

随着系统用户数的增加,数据库访问连接也不断增加,数据库上可能的阻塞可能性也随之增加。 对于DBA来说,我们更加关注正在发生的阻塞是什么类型的,这个阻塞在什么情况下是不可以被企业用户所接受的。例如一个在线交易系统,用户在付款的时候被阻塞了5秒钟,那么5秒钟是不能被用户所接受的。而对于一个报表系统,5秒钟不算什么,可能阻塞事件超过3分钟,那么用户才会开始抱怨。这个用户忍耐的时间,我们称为厥值(Threshold).

 

2. 监控阻塞的厥值

2.1 监控的目的

当某个阻塞超过假定的厥值后,DBA收到通知。

 

2.2 如何设定阻塞的厥值

SQL 提供了一个服务器配置选项 blocked process threshold ,该选项用于指定阈值(以秒为单位),超过该阈值

<think> 我们被要求提供自动监控SQL Server中死锁进程SQL的方法。根据之前的引用回答,我们可以总结出几种自动监控死锁的方法,包括使用扩展事件SQL Server代理作业、系统健康会话以及自定义监控存储过程等。 ### 方法1:使用扩展事件(Extended Events)自动捕获死锁 扩展事件SQL Server中用于性能监控的轻量级系统。我们可以创建一个扩展事件会话来自动捕获死锁信息,并将结果保存到文件中,然后定期分析这些文件。 #### 步骤: 1. **创建扩展事件会话**: 使用以下脚本创建一个扩展事件会话,用于捕获死锁图(deadlock graph): ```sql CREATE EVENT SESSION [DeadlockMonitor] ON SERVER ADD EVENT sqlserver.xml_deadlock_report ADD TARGET package0.event_file(SET filename = N'C:\Monitor\DeadlockMonitor.xel') -- 指定文件路径 WITH (MAX_MEMORY=4096 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=ON); GO ``` 注意:需要确保指定的文件路径存在,并且SQL Server服务账户有写入权限。 2. **启动会话**: ```sql ALTER EVENT SESSION [DeadlockMonitor] ON SERVER STATE = START; GO ``` 3. **配置SQL Server代理作业定期分析扩展事件文件**: 可以创建一个SQL Server代理作业,定期执行一个存储过程来读取扩展事件文件,解析死锁信息并存储到表中。 - 首先,创建一个表来存储死锁信息: ```sql CREATE TABLE [dbo].[DeadlockEvents]( [DeadlockID] [int] IDENTITY(1,1) NOT NULL, [EventTime] [datetime] NOT NULL, [DeadlockGraph] [xml] NOT NULL, CONSTRAINT [PK_DeadlockEvents] PRIMARY KEY CLUSTERED ([DeadlockID] ASC) ); ``` - 然后,创建存储过程来读取扩展事件文件并插入到表中: ```sql CREATE PROCEDURE [dbo].[usp_CollectDeadlockEvents] AS BEGIN INSERT INTO [dbo].[DeadlockEvents] ([EventTime], [DeadlockGraph]) SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP), [event_data].[EventTime]) AS [EventTime], [event_data].[DeadlockGraph] FROM (SELECT n.value('(@timestamp)[1]', 'datetime') AS [EventTime], n.query('.') AS [DeadlockGraph] FROM (SELECT CAST(event_data AS XML) AS [EventData] FROM sys.fn_xe_file_target_read_file('C:\Monitor\DeadlockMonitor*.xel', NULL, NULL, NULL)) AS [EventTable] CROSS APPLY [EventData].[nodes]('//event') AS [q](n) WHERE n.value('(@name)[1]', 'varchar(50)') = 'xml_deadlock_report') AS [event_data]; END ``` - 创建SQL Server代理作业,每天执行一次或多次此存储过程。 ### 方法2:使用系统健康会话(system_health) SQL Server 2008及更高版本内置了一个扩展事件会话`system_health`,它默认会捕获死锁信息。我们可以定期从该系统会话中提取死锁信息。 #### 步骤: 1. **查询system_health会话中的死锁事件**: 以下查询可以提取死锁图: ```sql SELECT [DeadlockGraph] = XEventData.XEvent.value('(data/value)[1]', 'varchar(max)') FROM (SELECT CAST([target_data] AS XML) AS TargetData FROM sys.dm_xe_session_targets st JOIN sys.dm_xe_sessions s ON s.[address] = st.[event_session_address] WHERE s.[name] = N'system_health' AND st.[target_name] = N'ring_buffer') AS Data CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData (XEvent); ``` 2. **将查询结果保存到表**: 同样可以创建代理作业,定期运行上述查询(或修改为插入表)来收集死锁信息。 ### 方法3:使用SQL Server代理警报 可以配置SQL Server代理警报来响应死锁事件。 #### 步骤: 1. **启用死锁跟踪标志**: ```sql DBCC TRACEON(1222, -1); -- 将死锁信息写入错误日志 ``` 2. **配置SQL Server代理警报**: - 在SQL Server代理中创建新的警报。 - 设置警报类型为“SQL Server性能条件警报”,计数器为`Number of Deadlocks/sec`,当值大于0时触发。 - 或者在“错误号”选项中指定错误号1205(死锁牺牲品的错误号)。 3. **为警报添加操作**: 可以配置警报触发时执行的操作,例如发送电子邮件通知,或者执行一个作业来收集当前死锁信息。 ### 方法4:使用自定义存储过程监控 参考引用[4],创建一个存储过程来自动收集死锁信息,并定期运行。 ### 总结 以上方法都可以实现自动监控死锁。推荐使用扩展事件(方法1)或系统健康会话(方法2)来捕获死锁信息,并结合SQL Server代理作业定期收集数据。这样,我们可以将死锁信息持久化到表中,便于后续分析。 ### 注意事项 - 自动监控死锁可能会产生大量数据,需要定期清理。 - 在生产环境中部署前,请先测试,避免影响性能。 ### 相关问题 1. 如何解析死锁图(Deadlock Graph)中的信息? 2. 如何设置死锁的自动通知(例如邮件通知)? 3. 如何减少SQL Server中的死锁发生? 4. 如何根据收集的死锁信息进行性能优化? [^1]: 使用扩展事件监控死锁。 [^2]: 利用系统健康会话收集死锁信息。 [^3]: 配置SQL Server代理警报响应死锁。 [^4]: 通过自定义存储过程自动收集死锁信息。 </think>在 SQL Server 中实现自动监控死锁进程 SQL 语句,推荐以下高效可靠的解决方案: --- ### 一、使用扩展事件 (Extended Events) 自动捕获死锁 **原理**:轻量级监控,捕获死锁图形完整 SQL 语句 **步骤**: 1. **创建扩展事件会话** ```sql CREATE EVENT SESSION [DeadlockMonitor] ON SERVER ADD EVENT sqlserver.xml_deadlock_report -- 捕获死锁图 ADD TARGET package0.event_file( SET filename = N'C:\Monitor\DeadlockMonitor.xel', -- 保存路径 max_file_size = 10 -- 文件大小(MB) ) WITH (STARTUP_STATE = ON); -- 服务启动时自动运行 GO ``` **关键参数**: - `xml_deadlock_report`:捕获死锁的 XML 格式报告 - `event_file`:保存到文件便于后续分析 2. **启动会话** ```sql ALTER EVENT SESSION [DeadlockMonitor] ON SERVER STATE = START; ``` 3. **定期解析死锁信息** 创建存储过程解析 .xel 文件: ```sql CREATE PROCEDURE usp_AnalyzeDeadlocks AS BEGIN SELECT event_data.value('(event/@timestamp)[1]','datetime') AS [Time], event_data.value('(event/data/value/deadlock/victim-process/@id)[1]','varchar(10)') AS VictimPID, event_data.query('(event/data/value/deadlock/process-list/process)') AS ProcessDetails -- 包含SQL语句 INTO DeadlockHistory FROM (SELECT CAST(event_data AS XML) AS event_data FROM sys.fn_xe_file_target_read_file('C:\Monitor\DeadlockMonitor*.xel', NULL, NULL, NULL) ) AS EventTable; END ``` **输出字段**: - `ProcessDetails`:包含死锁进程的完整 SQL 语句 - `VictimPID`:被牺牲的进程 ID 4. **配置 SQL Server 代理作业** - 定时执行存储过程(如每 15 分钟) - 添加邮件通知:死锁发生时自动发送警报[^1] --- ### 二、利用系统健康会话 (system_health) 自动监控 **原理**:使用内置会话捕获死锁(SQL Server 2008+ 默认启用) **查询死锁记录**: ```sql SELECT xed.value('@timestamp', 'datetime') AS [Time], xed.query('.') AS DeadlockGraph -- 完整死锁图 FROM ( SELECT CAST([target_data] AS XML) AS TargetData FROM sys.dm_xe_session_targets st INNER JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address WHERE s.name = 'system_health' ) AS Data CROSS APPLY TargetData.nodes('//event[@name="xml_deadlock_report"]') AS XEventData (xed) ORDER BY [Time] DESC; ``` **优势**: - 零配置,开箱即用 - 自动保留最近死锁记录(默认 5 个) --- ### 三、自定义死锁监控存储过程 **参考引用[4]创建自动化脚本**: ```sql CREATE PROCEDURE usp_AutoDeadlockMonitor @MinutesBack INT = 60 -- 监控最近N分钟 AS BEGIN SELECT dl.deadlock_id, dl.event_date, victim_process = dl.victim_process_id, blocking_process = dl.blocking_process_id, sql_text = t.text FROM ( -- 死锁基础信息 SELECT deadlock_id = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY event_time)), event_time, victim_process_id = victim_xml.value('@id', 'VARCHAR(10)'), blocking_process_id = blocking_xml.value('@id', 'VARCHAR(10)') FROM sys.dm_xe_session_targets st CROSS APPLY (SELECT CAST(st.target_data AS XML) ) AS x CROSS APPLY x.target_data.nodes('//event') AS e(event_xml) CROSS APPLY event_xml.nodes('//victim-process') AS v(victim_xml) CROSS APPLY event_xml.nodes('//blocking-process') AS b(blocking_xml) WHERE st.target_name = 'event_file' AND event_xml.value('@name','VARCHAR(50)') = 'xml_deadlock_report' AND event_time > DATEADD(MINUTE, -@MinutesBack, GETDATE()) ) dl CROSS APPLY sys.dm_exec_sql_text( CONVERT(VARBINARY(64), '0x' + blocking_xml.value('(./@sqlhandle)[1]','VARCHAR(200)'), 1) ) t; END ``` **执行**: ```sql EXEC usp_AutoDeadlockMonitor @MinutesBack = 30; -- 检查最近30分钟 ``` --- ### 四、死锁自动处理策略 1. **自动终止低优先级进程** ```sql ALTER DATABASE [YourDB] SET DEADLOCK_PRIORITY LOW; -- 指定库级别优先级 ``` 2. **代理作业自动终止阻塞源** ```sql CREATE PROCEDURE usp_KillDeadlockSource AS BEGIN DECLARE @BlockingSPID INT; SELECT TOP 1 @BlockingSPID = blocking_session_id FROM sys.dm_exec_requests WHERE blocking_session_id <> 0; IF @BlockingSPID IS NOT NULL EXEC('KILL ' + @BlockingSPID); END ``` --- ### 五、最佳实践建议 1. **监控部署流程**: ```mermaid graph TD A[创建扩展事件会话] --> B[配置SQL代理定时作业] B --> C[解析死锁XML存入历史表] C --> D[设置邮件警报] ``` 2. **关键指标**: - 死锁频率(次/小时) - 平均死锁持续时间(ms) - 高频死锁对象(表/索引) 3. **优化方向**: - 为高频死锁查询添加 `NOLOCK` 提示(需评估一致性风险) - 优化索引减少锁竞争 - 使用 `READ COMMITTED SNAPSHOT` 隔离级别[^3] --- ### 总结 通过扩展事件 + SQL Server 代理 + 自定义存储过程的组合方案,可实现: ✅ 自动捕获死锁图形 ✅ 记录完整 SQL 语句 ✅ 历史数据分析 ✅ 实时邮件警报 ✅ 自动终止进程(可选) > ⚠️ 生产环境建议先测试监控脚本的性能影响[^2] --- ### 相关问题 1. 如何解析死锁图(Deadlock Graph)中的关键信息? 2. 如何配置死锁发生时的自动邮件通知? 3. 哪些索引优化策略可减少死锁? 4. 如何区分死锁与普通阻塞? [^1]: 使用扩展事件实现自动化死锁监控。 [^2]: 通过SQL Server代理定期执行监控脚本。 [^3]: 修改隔离级别降低死锁概率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值