You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQL Server中查看休眠会话的未提交事务语句

如何在SQL Server中查看休眠会话的未提交事务语句

我来帮你搞定这个问题,顺便解答下你用DMV查询时遇到的疑惑:

核心查询:关联DMV获取未提交事务的SQL语句

当会话处于休眠状态时,sys.dm_exec_requests里不会有当前请求的记录,这时候得靠会话的最后执行SQL句柄来找到开启事务的语句。试试这个关联多个DMV的查询:

SELECT 
    s.session_id,
    t.transaction_id,
    dt.database_id,
    DB_NAME(dt.database_id) AS database_name,
    tat.name AS transaction_name,
    tat.transaction_begin_time,
    s.status AS session_status,
    COALESCE(er.command, '无活跃请求') AS current_command,
    est.text AS transaction_related_sql,
    eqp.query_plan
FROM sys.dm_tran_session_transactions t
JOIN sys.dm_exec_sessions s ON t.session_id = s.session_id
LEFT JOIN sys.dm_exec_requests er ON t.session_id = er.session_id
LEFT JOIN sys.dm_tran_database_transactions dt ON t.transaction_id = dt.transaction_id
LEFT JOIN sys.dm_tran_active_transactions tat ON t.transaction_id = tat.transaction_id
CROSS APPLY sys.dm_exec_sql_text(COALESCE(er.sql_handle, s.last_request_sql_handle)) est
OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) eqp
WHERE s.session_id = 57 -- 替换成你的目标会话ID
ORDER BY dt.database_id;

关键说明:

  • COALESCE(er.sql_handle, s.last_request_sql_handle):如果会话休眠(无活跃请求),就取会话最后一次执行的SQL句柄,这大概率就是开启事务但未提交的语句。
  • 关联sys.dm_tran_database_transactions可以看到事务涉及的数据库,sys.dm_tran_active_transactions能拿到事务的开始时间和名称。

解答你的DMV结果疑问

为什么sys.dm_tran_database_transactions只显示两行?

你提到在user_db里有两个未提交事务,但只看到一行user_db和一行tempdb的记录,大概率是因为:

  1. 嵌套事务的误导:SQL Server的嵌套事务并不真正生成多个独立事务——哪怕你执行了多次BEGIN TRANSACTION,最终只有最外层的事务会被提交/回滚,所以transaction_id只有一个,对应每个涉及的数据库生成一条记录(比如你的事务操作了user_db,同时隐式用到了tempdb,比如排序、临时表、统计信息更新等)。
  2. 事务计数的含义:sys.dm_tran_session_transactions里的transaction_count是会话中事务的嵌套层级数,不是独立事务的数量。比如嵌套两次事务,这个值会是2,但实际只有一个真实的事务ID。

为什么sys.dm_tran_active_transactions没返回有效信息?

如果这个DMV只显示一行无详细内容的记录,可能是因为事务处于“休眠”状态(没有正在执行的操作但未提交),此时它的transaction_type可能是2(用户事务),但name字段可能为空,你可以仔细看看transaction_begin_time和transaction_state字段(1表示活跃未提交)。

补充:通过锁信息定位事务

如果上面的查询还不够,你可以查看事务持有的锁,关联到对应的SQL语句:

SELECT 
    s.session_id,
    t.transaction_id,
    DB_NAME(l.resource_database_id) AS database_name,
    l.resource_type,
    l.resource_description,
    l.request_mode,
    est.text AS related_sql
FROM sys.dm_tran_locks l
JOIN sys.dm_tran_session_transactions t ON l.request_session_id = t.session_id
JOIN sys.dm_exec_sessions s ON l.request_session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(COALESCE(s.last_request_sql_handle, 0x0)) est
WHERE l.request_session_id = 57
ORDER BY l.resource_database_id;

这个查询能帮你看到事务锁住了哪些资源,以及对应的SQL语句,进一步确认未提交事务的来源。

内容的提问来源于stack exchange,提问作者Alexandr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 09:42:49