如何在SQL中通过动态视图监控数据库实时会话与死锁

梦瑶姑娘_5792

梦瑶姑娘_5792

2026-11-09

909人浏览

原创

sys.dm_exec_sessions 和 sys.dm_exec_requests 无法监控死锁,因其仅提供瞬时快照且不保留死锁上下文;真正可靠的是扩展事件(如 system_health 中的 xml_deadlock_report)。

如何在sql中通过动态视图监控数据库实时会话与死锁

sys.dm_exec_sessions 和 sys.dm_exec_requests 这两个动态管理视图(DMV)本身不能“监控死锁”,它们只反映某一毫秒的会话快照。死锁一旦被 SQL Server 检测并解除,相关会话通常已回滚或终止,sys.dm_exec_requests 中的记录迅速消失,sys.dm_exec_sessions 也不保留死锁上下文。你查不到死锁链,不是查询写得不对,而是数据根本没在那里。

真正能捕获死锁的唯一可靠来源是扩展事件(XEvent),尤其是预启用的 system_health 会话。它默认收集 xml_deadlock_report 事件,保留在环形缓冲区中(约 4 小时,受内存压力影响)。别试图用视图“实时”看死锁——那是误解了死锁的本质:它是瞬态冲突事件,不是持续状态。

要查最近发生的死锁图,执行:

SELECT CAST(target_data AS XML) 
FROM sys.dm_xe_session_targets st 
JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address 
WHERE s.name = 'system_health'

然后在返回的 XML 中搜索 节点。注意:结果是 XML,需展开查看资源争用、进程堆栈、输入缓冲区等完整现场。


怎么用 DMV 查当前阻塞链(不是死锁)

阻塞是可观察的瞬时状态,但比死锁“活得久一点”。关键不是单次查询,而是理解 blocking_session_id 的含义和局限:

  • blocking_session_id > 0 表示该请求正被另一个会话阻塞
  • 但这个值只在阻塞发生当下有效;一旦被 Kill 或超时释放,就归零
  • 单靠 sys.dm_exec_requests 不知道谁持锁,必须关联 sys.dm_tran_locks 和 sys.dm_exec_sql_text

推荐组合查询(带锁表名和 SQL 文本):

DrugBank 数据库
DrugBank 数据库

访问并分析来自 DrugBank 数据库的全面药物信息,包括药物属性、相互作用、靶点、通路、化学结构和药理学数据。用于药物数据、药物发现研究、药理学研究、药物-

下载
SELECT 
  r.session_id,
  r.blocking_session_id,
  t.text AS [SQL语句],
  o.name AS [被锁表名],
  l.resource_type,
  l.request_mode,
  l.request_status
FROM sys.dm_tran_locks l
JOIN sys.partitions p ON l.resource_associated_entity_id = p.hobt_id
JOIN sys.objects o ON p.object_id = o.object_id
JOIN sys.dm_exec_requests r ON l.request_session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.blocking_session_id > 0 OR l.request_session_id IN (
  SELECT blocking_session_id 
  FROM sys.dm_exec_requests 
  WHERE blocking_session_id > 0
)
  • sys.dm_tran_locks 是锁信息唯一权威源,resource_description 可定位到具体页或键
  • sys.dm_exec_sql_text(r.sql_handle) 必须用 CROSS APPLY,不能用 LEFT JOIN(否则可能丢行)
  • 如果 t.text 为空,说明该会话已结束或 handle 失效,需结合 sys.dm_exec_sessions 查 login_time 和 last_request_end_time 判断活跃性

为什么不能用 sp_who2 或 sp_lock 查死锁

sp_who2 和 sp_lock 在 SQL Server 2022 中已被标记为“过时”,微软明确不推荐用于生产诊断:

  • sp_who2 仅包装 sys.dm_exec_sessions 和 sys.dm_exec_requests,输出格式老旧,不包含等待资源详情,无法识别锁类型(如 KEY、PAGE、OBJECT)
  • sp_lock 底层调用已废弃的 sys.syslockinfo,返回结果不稳定,在高并发下常漏锁、错行,且不支持现代锁粒度(如意向锁、键范围锁)
  • 二者均不输出死锁图结构,也无法关联系统进程与应用连接字符串(host_name、program_name 需从 sys.dm_exec_sessions 显式查)

替代方案很简单:直接查 DMV。例如查所有阻塞源头:

SELECT 
  s.session_id,
  s.host_name,
  s.program_name,
  s.login_name,
  r.status,
  r.command,
  r.wait_type,
  r.wait_time
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
WHERE s.session_id IN (
  SELECT DISTINCT blocking_session_id 
  FROM sys.dm_exec_requests 
  WHERE blocking_session_id  0
)
  • 注意过滤掉 status = 'sleeping' 的会话(可能是未提交事务的空闲连接)
  • wait_type 为 LCK_M_XX 类型才表明真正在等锁;若为 ASYNC_NETWORK_IO 或 PAGEIOLATCH_XX,阻塞根源不在锁本身

死锁长期留存必须建专用 XEvent 会话

system_health 是轻量兜底方案,但环形缓冲区不可控,容易被覆盖。生产环境必须建专用会话,把 xml_deadlock_report 输出到文件:

  • 目标类型选 event_file,路径设为独立磁盘(避免与数据文件争 I/O)
  • 启用 MAX_FILE_SIZE = 100 MB 和 MAX_ROLLOVER_FILES = 10 实现自动滚动
  • 添加 action 如 sqlserver.database_name、sqlserver.client_app_name,方便按业务分类分析

创建语句核心片段(省略完整 DDL):

CREATE EVENT SESSION [capture_deadlocks] ON SERVER 
ADD EVENT sqlserver.xml_deadlock_report(
  ACTION(sqlserver.database_name, sqlserver.client_app_name)
)
ADD TARGET package0.event_file(
  SET filename=N'D:\XEvents\deadlocks.xel',
      max_file_size=(100),
      max_rollover_files=(10)
)
  • 不要设 STARTUP_STATE = ON 后就不管——需定期检查文件是否写满、磁盘是否告警
  • .xel 文件可用 SSMS 图形化打开,也可用 T-SQL 查询:sys.fn_xe_file_target_read_file
  • 最容易被忽略的一点:XML 中的 inputbuf 可能被截断,长 SQL 需结合 sqlserver.sql_text action 补全

死锁监控不是配个视图就能跑起来的事。它依赖对事件本质的理解、对 DMV 边界条件的清醒认知,以及对 XEvent 文件生命周期的主动管理。想靠一个 SELECT 解决所有问题,只会反复看到“查不到”。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

数据库

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4863

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

991

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1269

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6901

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3583

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6880

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

9581

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1290

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1132

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
DBeaver生态工具dbvr官方手册
DBeaver生态工具dbvr官方手册

共0课时 | 0人学习

DBeaver AI数据隐私指南
DBeaver AI数据隐私指南

共0课时 | 0人学习