应直接查v$transaction的used_ublk定位高占用事务,>10000(即>80MB)属高风险,尤其关注status='INACTIVE'或username为空但program含oracle@host(J000)的残留事务,并关联v$session的module/action精确定位业务源头。

直接看 v$transaction 的 used_ublk,别只盯着 ASH 或 SQL_ID —— 长事务对 undo 的真实占用,在事务级视图里才露真容。
查 v$transaction 找高占用事务
ASH(v$active_session_history)采样不到 undo 写入主体,它看到的多是前台会话在 ON CPU 或短时等待,真正持续占块的是未提交事务本身。必须跳过采样层,直击事务状态。
-
used_ublk是关键指标:单位为数据库块(默认 8KB),>10000 表示已用超 80MB undo 空间,属高风险阈值 - 执行:
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 - 特别注意
status = 'INACTIVE'的会话:它可能已断开连接,但事务仍开着,used_ublk不降反升 - 若
username为空、program类似oracle@host (J000),大概率是 job 进程在跑未提交的批量任务
关联 v$session 判定源头模块
光有 SID 和 used_ublk 不够,得知道是谁写的逻辑、在哪跑的。Oracle 的 module 和 action 字段常被应用层埋点,比 SQL_TEXT 更稳定可靠。
- 加
SELECT s.module, s.action, s.client_info, s.osuser到上一条查询中,能快速定位到具体业务模块(如module = 'OrderBatchProcessor') - 避免依赖
sql_id:长事务内可能只执行一次 DML,后续全是空闲等待,sql_id早已为空或为系统递归语句(如0000000000000000) - 如果
module是通用框架名(如DBMS_SCHEDULER),再查dba_scheduler_jobs对应的job_action,确认是否含显式BEGIN ... END;且无COMMIT
交叉验证 undo 表空间是否卡住
事务没释放只是表象,底层可能是 undo 表空间无法回收旧区段,导致新事务被迫争抢剩余空间。这时单杀会话治标不治本。
- 查
DBA_UNDO_EXTENTS:重点关注STATUS = 'EXPIRED'的占比,若长期低于 20%,说明 undo 段老化慢,purge 压力大 - 查
V$UNDOSTAT:观察MAXCONCURRENCY是否频繁接近或超过UNDO_RETENTION设置值;同时看UNDOBLKS/TXNCOUNT的增速,若该比值持续 > 500,表示平均每个事务写入 undo 块过多,可能含大更新 - 注意:即使启用了
AUTOEXTEND,undo 表空间填满后也会报ORA-30036: unable to extend segment,但此时事务已卡在分配阶段,不会反映在used_ublk上升趋势里
最易被忽略的一点:v$transaction 中的 start_time 是事务开启时间,不是最后活动时间;一个事务可能 idle 39 分钟,只在第 40 分钟执行 COMMIT —— 这期间它始终持有 undo 块,而 ASH 里几乎看不到样本。监控脚本若只查“最近活跃”,会漏掉这类静默杀手。


















