KILL后事务回滚不可中断,需查sys.dm_exec_requests中status='rollback'或command='ROLLBACK',结合percent_complete、estimated_completion_time及wait_type(如WRITELOG)判断进度;DBCC OPENTRAN查不到回滚中事务,因其仅显示未提交的活跃事务。

如何识别正在回滚的事务(KILL后卡在“正在回滚”)
当执行 KILL 命令后看到“正在回滚”,说明 SQL Server 正在应用事务日志中的前像(before-image)来撤销已写入缓存但未提交的修改。这个过程不可中断,且耗时取决于事务修改的数据量、日志记录密度和磁盘 I/O 能力。
实时确认是否真在回滚,优先查 sys.dm_exec_requests:
SELECT session_id, status, command, percent_complete,
estimated_completion_time, wait_type, last_wait_type
FROM sys.dm_exec_requests
WHERE command = 'ROLLBACK' OR status = 'rollback';
-
percent_complete非零值表示回滚进度可估算(仅对某些操作如大事务 UPDATE/DELETE 有效) -
estimated_completion_time单位是毫秒,但对复杂回滚常严重不准,仅作粗略参考 - 若
wait_type是LOGBUFFER或WRITELOG,说明正密集刷日志页,此时强行重启实例会延长后续启动恢复时间
为什么 DBCC OPENTRAN 看不到“正在回滚”的事务
DBCC OPENTRAN 只显示仍处于活动状态(active)、尚未提交或回滚的事务,不包含已发出 ROLLBACK 或被 KILL 后进入回滚阶段的事务。这是最容易误解的一点——它不是“所有未完成事务”的总览,而是“当前持有锁且未结束的活跃事务”快照。
- 被
KILL的会话一旦进入回滚,就从sys.dm_tran_active_transactions中移除,DBCC OPENTRAN自然查不到 - 若想追溯是谁触发了回滚,需提前开启
QUERY_STORE或捕获sql_statement_completedXEvent,否则只能靠监控工具的历史记录 - 注意:SQL Server 2019+ 中
sys.dm_tran_database_transactions的database_transaction_state字段为 2 表示“回滚中”,但该视图不暴露会话 ID,需关联sys.dm_tran_session_transactions
用动态管理视图组合定位回滚源头
单靠一个 DMV 不够,要拼出完整链路:哪个会话、执行了什么语句、改了多少日志记录、卡在哪类资源上。
关键组合查询:
SELECT r.session_id, r.status, r.command, r.cpu_time, r.logical_reads,
t.transaction_id, t.database_transaction_begin_time,
dt.database_transaction_log_bytes_used,
s.host_name, s.program_name, s.login_name
FROM sys.dm_exec_requests r
JOIN sys.dm_tran_session_transactions st ON r.session_id = st.session_id
JOIN sys.dm_tran_active_transactions t ON st.transaction_id = t.transaction_id
JOIN sys.dm_tran_database_transactions dt ON t.transaction_id = dt.transaction_id
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
WHERE r.command = 'ROLLBACK';
-
database_transaction_log_bytes_used值越大,通常意味着回滚越久;超过 100MB 就该警惕 -
logical_reads高但cpu_time低,可能卡在磁盘写入(WRITELOG)或锁等待(LCK_M_U) -
program_name为Microsoft SQL Server Management Studio时,大概率是人工 KILL,而非应用层超时触发
事务日志空间与回滚性能的真实制约点
回滚慢,往往不是 CPU 或内存瓶颈,而是日志文件(LDF)本身的设计缺陷或 I/O 延迟。
- 如果 LDF 文件位于高延迟存储(如网络共享盘、慢速 SATA SSD),
WRITELOG等待会急剧放大回滚时间 - 日志文件自动增长(autogrow)在回滚中被频繁触发,会导致日志碎片化,进一步拖慢
Log Writer线程写入速度 - 使用简单恢复模式时,检查点(checkpoint)无法截断日志,
log_reuse_wait_desc查出来是ACTIVE_TRANSACTION,其实背后就是某个长回滚事务占着日志空间不放 - 不要依赖
DBCC SQLPERF(logspace)的“Log Space Used %”判断回滚压力——它反映的是 VLF(Virtual Log File)占用,而回滚真正卡住的是物理写入带宽
最常被忽略的一点:回滚过程本身会产生新的日志记录(用于记录回滚动作),所以极端情况下,一个 500MB 的事务回滚,可能额外生成 200MB 日志。这会让本就紧张的日志盘更快见底。

















