tempdb中挂起事务的含义及事务来源追踪方法咨询
生产环境查询超时与未提交事务排查问题
我在生产环境查询特定表时遇到超时问题,怀疑存在未提交事务,于是执行了以下SQL查询:
SELECT trans.session_id AS [SESSION ID] ,ESes.host_name AS [HOST NAME] ,login_name AS [Login NAME] ,trans.transaction_id AS [TRANSACTION ID] ,tas.name AS [TRANSACTION NAME] ,tas.transaction_begin_time AS [TRANSACTION BEGIN TIME] ,tds.database_id AS [DATABASE ID] ,DBs.name AS [DATABASE NAME] FROM sys.dm_tran_active_transactions tas JOIN sys.dm_tran_session_transactions trans ON (trans.transaction_id = tas.transaction_id) LEFT OUTER JOIN sys.dm_tran_database_transactions tds ON (tas.transaction_id = tds.transaction_id) LEFT OUTER JOIN sys.databases AS DBs ON tds.database_id = DBs.database_id LEFT OUTER JOIN sys.dm_exec_sessions AS ESes ON trans.session_id = ESes.session_id WHERE ESes.session_id IS NOT NULL
查询结果显示同一[SESSION ID](218)对应两条记录,一条对应数据库tempdb,另一条对应我的应用数据库:
SESSION ID, Login Name, ... TRANSACTION BEGIN TIME, DATABASE NAME, 218, MyAppSQLUser, 15 minutes ago, tempdb 218, MyAppSQLUser, ..., MyDatabase
执行KILL 218后超时问题解决,现咨询:
- tempdb对应的记录意味着什么?为何会存在?
- 后续应采取哪些步骤?如何在未来追踪此类事务的来源以定位根因?
问题1:tempdb对应的记录含义与存在原因
- 这条记录说明会话218的事务在
tempdb中存在事务上下文。SQL Server中,当会话开启事务后,如果在事务内执行了需要写入tempdb的操作——比如创建临时表/表变量、执行排序或哈希操作生成工作文件/工作表,就会在tempdb中生成该事务的关联记录。 - 你看到的两条记录本质是同一个跨数据库事务的不同分支:主事务在你的应用数据库
MyDatabase,但因为操作涉及tempdb,所以tempdb会同步生成该事务的记录,这是SQL Server处理跨库事务(哪怕其中一方是tempdb)的正常机制。
问题2:后续步骤与未来追踪方案
即时排查步骤
- 检查应用代码逻辑:排查使用
MyAppSQLUser账号的应用程序,确认是否存在未正确提交/回滚事务的情况——比如异常捕获后未处理事务、连接池复用导致事务残留。 - 分析会话执行详情:问题重现时,执行以下查询获取会话的当前及历史SQL,定位具体操作:
-- 获取会话当前执行的SQL SELECT dest.text FROM sys.dm_exec_requests der CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) dest WHERE der.session_id = 218; -- 获取会话的历史执行语句 SELECT dest.text, deqs.last_execution_time FROM sys.dm_exec_query_stats deqs CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) dest WHERE deqs.session_id = 218; - 核实事务隔离级别:确认应用使用的事务隔离级别是否过高(如
SERIALIZABLE),这类级别更容易引发锁等待和长时间未提交事务。
长期追踪方案
- 使用扩展事件监控(性能影响远低于SQL Server Profiler):创建追踪会话,捕获以下事件:
Begin Transaction、Commit Transaction、Rollback Transaction,关联会话ID与SQL语句;Lock:Timeout、Lock:Deadlock,及时发现锁等待问题。
- 设置长时间事务告警:定期执行监控查询,筛选出持续时间超过阈值(如5分钟)的事务,示例查询:
SELECT trans.session_id, ESes.host_name, login_name, DATEDIFF(MINUTE, tas.transaction_begin_time, GETDATE()) AS [事务持续时长(分钟)], DBs.name AS [数据库名], dest.text AS [最后执行SQL] FROM sys.dm_tran_active_transactions tas JOIN sys.dm_tran_session_transactions trans ON trans.transaction_id = tas.transaction_id LEFT JOIN sys.dm_tran_database_transactions tds ON tas.transaction_id = tds.transaction_id LEFT JOIN sys.databases DBs ON tds.database_id = DBs.database_id LEFT JOIN sys.dm_exec_sessions ESes ON trans.session_id = ESes.session_id LEFT JOIN sys.dm_exec_requests der ON trans.session_id = der.session_id OUTER APPLY sys.dm_exec_sql_text(der.sql_handle) dest WHERE ESes.session_id IS NOT NULL AND DATEDIFF(MINUTE, tas.transaction_begin_time, GETDATE()) > 5; - 增强应用端日志:在应用中添加事务相关日志,记录事务的开启、提交/回滚位置,以及异常场景下的事务处理逻辑,方便快速定位代码层面问题。
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

