v$active_session_history(ASH)不直接显示undo占用者,因undo写入由后台进程完成,ASH中多见ON CPU或短时log file sync;真正反映undo压力的是触发回滚段维护的DML操作引发的高频率递归SQL,如索引分裂、undo header更新等;需结合session_state='ON CPU'、sql_opname∈('INSERT','UPDATE','DELETE','DDL')、空event但sql_id为0000000000000000或系统递归语句(如select /*+ rule */ ... from sys.undo$),并依据program/module定位源头;ASH快照有限,须关联v$transaction和v$session查used_ublk高的事务,>10000(即>80MB)属高风险,尤其注意INACTIVE会话残留事务;最后用DBA_UNDO_EXTENTS与V$UNDOSTAT交叉验证undo表空间是否卡住,重点关注EXPIRED占比、MAXCONCURRENCY及UNDOBLKS/TXNCOUNT增速。
查 v$active_session_history 里 ON CPU + UNDO 相关递归 SQL
ash 本身不直接记录“谁在用 undo”,因为 undo 写入由后台进程(如 ora_dbw0_*)完成,前台会话采样时往往只看到 on cpu 或极短的 log file sync。真正暴露 undo 压力的,是那些触发大量回滚段维护的 dml 操作——它们会生成高频率的递归 sql,比如索引块分裂、undo header 更新等,在 ash 中表现为 sql_id 不是你写的 delete/update,而是系统生成的内部语句。
实操建议:
- 别只过滤原始 SQL 的
sql_id,要查session_state = 'ON CPU'且sql_opname IN ('INSERT', 'UPDATE', 'DELETE', 'DDL')的样本 - 重点关注
event为空但sql_id是0000000000000000或以SQL_ID为前缀的递归语句(如select /*+ rule */ ... from sys.undo$) - 结合
program和module判断来源:比如module = 'BatchDelete'却大量出现ON CPU样本,基本就是 undo 分配或索引分裂在后台吃 CPU
关联 v$transaction 和 v$session 定位真实事务持有者
ASH 只是快照,不能替代事务级视图。一个长时间未提交的事务可能在 ASH 里只留下几条零星样本,但它持续占用 undo 段。必须立刻查 v$transaction 找出 used_ublk 高的事务,再反向关联到 v$session。
实操建议:
- 运行:
SELECT s.sid, s.serial#, s.username, s.program, t.used_ublk, t.start_time FROM v$session s JOIN v$transaction t ON s.taddr = t.addr ORDER BY t.used_ublk DESC FETCH FIRST 5 ROWS ONLY -
used_ublk单位是数据库块(通常 8KB),>10000 表示已用超 80MB undo 空间,属高风险 - 若
username为空但program是oracle@host (J000),说明是 job 进程在跑未提交的批量操作 - 注意
status为INACTIVE的会话:它可能已断开但事务未 rollback,v$transaction仍存在,这是最常见的 undo 泄漏源
用 DBA_UNDO_EXTENTS + V$UNDOSTAT 交叉验证 undo 压力是否真实
单纯看会话占用不等于系统有问题。有些大事务确实需要大量 undo,但只要空间能回收,就不算故障。关键要看 undo 表空间是否被“卡住”:比如 EXPIRED 区块极少、MAXCONCURRENCY 持续 >20、UNDOBLKS 增速远高于 TXNCOUNT。
实操建议:
- 查状态分布:
SELECT STATUS, SUM(BLOCKS) BLOCKS_CNT FROM DBA_UNDO_EXTENTS WHERE TABLESPACE_NAME = 'UNDOTBS1' GROUP BY STATUS—— 若EXPIRED占比 - 查压力峰值:
SELECT BEGIN_TIME, UNDOBLKS, TXNCOUNT, MAXCONCURRENCY FROM V$UNDOSTAT ORDER BY BEGIN_TIME DESC FETCH FIRST 10 ROWS ONLY—— 若某快照中UNDOBLKS涨了 5 倍而TXNCOUNT只涨 1.2 倍,说明有事务在疯狂写 undo 而不释放 -
MAXCONCURRENCY≥50+ 且持续多快照,基本可断定 undo segment 头争用严重,此时enq: US - contention会在v$session_event中高频出现,ASH 里却几乎看不到
别依赖 ASH 报告里的 “Top SQL” 页面
标准 ASH 报告(@?/rdbms/admin/ashrpt.sql)的 “Top SQL with Waiting Events” 默认按等待时间排序,而 undo 相关消耗多数不体现为前台等待。你很可能看到一堆 db file sequential read 或 log file sync,但根本原因却是某个事务在后台持续分配 undo 块。
实操建议:
- 跳过报告默认页,直接查 “Blocking Session Summary” 和 “Top Sessions by DB Time” —— 如果某会话 DB Time 极高但 SQL_ID 为空、event 为
ON CPU,它大概率就是 undo 消耗源头 - 报告里出现高频
enq: US - contention,说明前台会话正在抢 undo segment,这时要立刻查v$session_event中该 event 的p1(undo segment#),再定位对应段名 - ASH 报告时间窗口选太宽(比如 1 小时)会稀释瞬时峰值,建议按分钟级切片:生成两个相邻 5 分钟报告,对比
DB Time和Active Sessions曲线突刺点
真实 undo 压力往往藏在“没等待、不报错、但空间涨得飞快”的静默状态里。ASH 是线索,不是证据;它告诉你“可能有问题”,但最终得靠 v$transaction、V$UNDOSTAT 和 DBA_UNDO_EXTENTS 三者交叉确认。尤其当 MODULE 为空、SQL_ID 为 0、EVENT 为空时,别急着优化 SQL,先查事务是否还挂着。











