ASH不能准确估算回滚剩余时间,因其仅采样运行中会话状态,而SMON并行回滚不体现SQL执行链,等待事件只反映阻塞而非进度,且回滚速度非线性、无sql_id、易误判。
直接看 v$fast_start_transactions 和 x$ktuxe,ash 只能辅助定位阻塞源头,不能准确估算回滚剩余时间。
为什么不能靠 ASH 估算回滚完成时间
ASH(v$active_session_history)采样的是「正在运行」的会话状态,而事务回滚由 SMON 进程以并行方式驱动,其内部恢复工作不体现在用户会话的 SQL 执行链中。你看到的 wait for a undo record 或 checkpoint incomplete 等等待事件,在 ASH 里只反映“被卡住”,不反映“还剩多少 undo 块要处理”。
常见误判现象:
- ASH 显示某会话长时间处于
enq: TX - row lock contention,但实际它只是被回滚中的事务锁住,并非它自己在回滚 - 用
ash.sql_id关联到 DML 语句,误以为该 SQL 正在执行回滚 —— 实际上回滚没有对应的sql_id - 按 ASH 中
sample_time的跨度计算“已耗时”,却忽略回滚速度非线性(尤其在 undo 空间紧张或 I/O 压力大时会明显变慢)
真正有效的监控视图组合
回滚进度必须从 Oracle 恢复子系统内部指标入手,核心是两个视图:
-
v$fast_start_transactions:提供undoblocksdone和undoblockstotal,可算出完成百分比;字段cputime是 SMON 已消耗 CPU 秒数,用于粗略倒推速率 -
x$ktuxe:底层事务条目,ktuxesiz表示当前活跃 undo 块数;连续两次查询差值除以间隔秒数,就是实时回滚速率(单位:undo 块/秒)
典型查询示例:
SELECT usn, state, undoblockstotal "Total", undoblocksdone "Done",
ROUND(100 * undoblocksdone / NULLIF(undoblockstotal, 0), 2) "% Done",
DECODE(cputime, 0, 'unknown',
TO_CHAR(SYSDATE + ((undoblockstotal - undoblocksdone) /
(NULLIF(undoblocksdone, 0) / NULLIF(cputime, 0))) / 86400,
'HH24:MI:ss DD-MON-YYYY')) "Est. Finish"
FROM v$fast_start_transactions;
注意:v$fast_start_transactions 只显示「崩溃恢复」或「实例启动后触发的快速启动恢复」相关事务;若事务是正常会话中被 ROLLBACK,需查 x$ktuxe 配合 v$transaction。
如何关联事务和原始会话
回滚事务本身没有用户名、SQL_ID,但可通过地址反向绑定发起者:
- 查
v$transaction.taddr→ 关联v$session.saddr→ 得到原始sid、username、program - 查
x$ktuxe.ktuxeusn/ktuxeslt/ktuxesqn→ 转成十进制 XID → 在v$transaction中匹配xidusn/xidslot/xidsqn - 注意:如果原始会话已断开(如网络中断),
v$session中对应记录消失,只能靠dba_hist_active_sess_history查历史 SQL(但无法确认是否就是该回滚事务发起者)
关键命令:
SELECT s.sid, s.username, s.program, t.start_time, t.used_ublk * (SELECT value/1024/1024 FROM v$system_parameter2 WHERE name='db_block_size') "MB Used" FROM v$transaction t, v$session s WHERE t.addr = s.taddr(+);
容易被忽略的性能陷阱
回滚时间不仅取决于 undo 块数量,更受以下因素制约:
-
undo_tablespace空间争用:当dba_undo_extents.status IN ('ACTIVE', 'UNEXPIRED')占比超 70%,SMON 回滚会频繁等待空间分配 -
FAST_START_PARALLEL_ROLLBACK参数设为HIGH或LOW时,Oracle 可能因 bug 导致并行进程多数空闲(查v$fast_start_servers.state,若仅一个为RECOVERING其余全IDLE,建议临时设为FALSE) - 底层存储 I/O 延迟高时,
ktuxesiz下降速率会骤减,此时看v$session_wait中direct path read temp或db file sequential read等等待占比更有意义
最常被跳过的动作:没检查 v$undostat.tuned_undoretention 是否被动态拉高 —— 这会导致 undo 段无法及时重用,间接拖慢回滚。











