应查v$transaction定位高used_ublk未提交事务,used_ublk>10000(超80MB)属高风险,结合v$session的module、program、logon_time等字段溯源业务逻辑,同时验证DBA_UNDO_EXTENTS和V$UNDOSTAT确认undo表空间健康状态。

不能直接从 ASH 查到“谁在锁 UNDO 段”——因为 UNDO 写入由后台进程完成,前台会话采样时几乎不显式持有 UNDO 段锁;真正要抓的是高 used_ublk 的未提交事务。
查 v$transaction 找高占用事务
ASH 中的 ON CPU + 空 event + 系统递归 sql_id(如 0000000000000000)只是线索,不是证据。真实 UNDO 压力来自未提交事务持续分配回滚段空间。必须立刻查 v$transaction:
- 运行:
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,属高风险阈值 - 注意
username为空但program是oracle@host (J000):很可能是 job 进程在跑批量 DML 且未提交 -
status为INACTIVE的会话也要盯紧——它可能已断连,但事务仍活在 undo 段里
关联 v$session 定位源头程序和模块
光有 SID 不够,得知道是谁写的逻辑、在哪跑的:
- 结合
v$session的module和program字段判断业务上下文:比如module = 'BatchDelete'却对应高used_ublk,基本可断定是索引分裂或 undo header 更新在后台吃资源 - 若
sql_id为空或为0000000000000000,别再翻v$sql——它大概率是递归 SQL,查不到原始语句,应转向应用日志或监控埋点 - 对
program含ora_w00_、ora_dbw0_的行,忽略——那是后台进程,不是源头
验证 undo 表空间是否卡住
高 used_ublk 事务只是“症状”,得确认 undo 表空间本身有没有异常:
- 查
DBA_UNDO_EXTENTS:重点关注STATUS = 'EXPIRED'的占比,若长期低于 10%,说明 undo 段无法及时回收 - 查
V$UNDOSTAT:看MAXCONCURRENCY是否频繁接近或超过设置值,以及UNDOBLKS/TXNCOUNT的增速是否陡峭——这两者突增往往预示大量短事务并发写入 - 不要只盯着
dba_free_space:undo 表空间“满”不等于磁盘满,而是活跃事务把可用 undo extent 都占住了
真正难处理的不是那个 used_ublk 最高的会话,而是它背后没被监控到的批量作业——比如凌晨跑的 ETL 脚本,只在 v$active_session_history 里留下几条 ON CPU 样本,却在 v$transaction 里挂了 6 小时不动。这时候查不到 SQL,只能靠 module + logon_time + 应用排期交叉比对。


















