应查V$UNDOSTAT看MAXCONCURRENCY是否持续≥20或频繁达50+,结合UNDOBLKS与TXNCOUNT突刺判断Undo压力;再用DBA_UNDO_EXTENTS检查EXPIRED占比是否低于20%;联合V$SESSION与V$TRANSACTION定位INACTIVE长事务;确保undo_management=AUTO,合理设置undo_retention并排查底层存储异常。
查 V$UNDOSTAT 看 UNDO 压力峰值是否持续超标
awr 报告本身不直接标出“undo争用”,但 v$undostat 是底层核心视图,awr 快照正是基于它采集。关键不是看平均值,而是盯住每10分钟一个的快照中 undoblks 和 txncount 的突刺——尤其当 maxconcurrency 长期 ≥ 20 或频繁跳到 50+,说明事务在抢回滚段头或区分配锁。
实操建议:
- 执行
SELECT BEGIN_TIME, END_TIME, UNDOBLKS, TXNCOUNT, MAXCONCURRENCY FROM V$UNDOSTAT ORDER BY BEGIN_TIME DESC FETCH FIRST 20 ROWS ONLY,观察最近20个快照; - 若某段时间
MAXCONCURRENCY持续高企,且对应时段UNDOBLKS增速远超TXNCOUNT(比如事务数涨2倍,Undo块涨5倍),大概率存在长事务或未提交事务卡住空间; - 注意
UNDOBLKS单位是数据库块(通常8KB),不是字节,别误算成MB。
用 DBA_UNDO_EXTENTS 判断状态分布是否失衡
Undo 表空间爆满,往往不是总量不够,而是 ACTIVE / UNEXPIRED 区块堆积,EXPIRED 区块太少——说明 undo_retention 设得过长,或空间回收机制被阻塞。正常情况下,STATUS = 'EXPIRED' 的区块应占总量 30%~60%,低于20%就危险。
实操建议:
- 运行
SELECT STATUS, SUM(BLOCKS) BLOCKS_CNT, TRUNC(SUM(BLOCKS)*8/1024) SIZE_MB FROM DBA_UNDO_EXTENTS WHERE TABLESPACE_NAME = 'UNDOTBS1' GROUP BY STATUS(把UNDOTBS1替换为你的表空间名); - 如果
ACTIVE+UNEXPIRED占比 > 90%,且EXPIRED接近 0,优先排查长事务(见下一条),而不是急着扩容; -
UNEXPIRED过高还可能因undo_retention被设为 86400(24小时)却无自动扩展,导致 Oracle 不敢回收——此时调低 retention 比加数据文件更治本。
定位真实长事务:别只信 V$TRANSACTION 的 START_TIME
V$TRANSACTION.START_TIME 显示的是事务开始时间,但很多“长事务”其实是空闲连接挂着未提交(比如应用层连接池没设超时),这类事务在 V$TRANSACTION 里能看到,但在 V$SESSION 中 STATUS 是 INACTIVE,SQL_ID 为空。单靠这个视图会漏掉一半问题。
实操建议:
- 联合查:
SELECT s.sid, s.serial#, s.username, s.status, s.sql_id, t.start_time, t.used_ublk, t.used_urec FROM V$SESSION s JOIN V$TRANSACTION t ON s.saddr = t.ses_addr ORDER BY t.start_time; - 重点筛
STATUS = 'INACTIVE'且USED_UBLK > 10000的行——这代表它占着大量 Undo 块却不干活; - 对这类 SID,立刻执行
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;杀之前可先SELECT sql_text FROM V$SQL WHERE sql_id = 'xxx'看它最初执行了什么(如果还能查到)。
调整回滚段分配策略:别碰 rollback_segments 参数
Oracle 9i 后默认启用 AUM(Automatic Undo Management),rollback_segments 是手动管理模式遗留参数。现在强行指定它,会导致实例启动失败或回滚段无法自动伸缩——这不是优化,是倒退。
实操建议:
- 确认
undo_management是AUTO:SHOW PARAMETER undo_management; - 真正可控的是
undo_retention和 Undo 表空间是否开启AUTOEXTEND; - 如果频繁出现 ORA-01555,优先检查长查询是否真需要那么久的一致性读,而不是盲目加大
undo_retention; - OLTP 系统建议
undo_retention设为 900~3600 秒(15~60分钟),足够覆盖绝大多数事务,再高收益极低,反而拖慢空间回收。
最常被忽略的一点:Undo 表空间的数据文件路径权限、磁盘剩余空间、ASM diskgroup 是否 offline,这些底层异常不会报错在 AWR 里,但会让 V$UNDOSTAT 的 UNDOBLKS 突然归零或停滞——先看操作系统层面有没有写入失败日志,再查数据库视图。


















