如何在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的记录,大概率是因为:
- 嵌套事务的误导:SQL Server的嵌套事务并不真正生成多个独立事务——哪怕你执行了多次
BEGIN TRANSACTION,最终只有最外层的事务会被提交/回滚,所以transaction_id只有一个,对应每个涉及的数据库生成一条记录(比如你的事务操作了user_db,同时隐式用到了tempdb,比如排序、临时表、统计信息更新等)。 - 事务计数的含义:
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
相关产品推荐
相关产品推荐

