ORA-30036报错时,UNDO表空间大概率已耗尽或被长事务占满;需通过AWR报告中「Undo Segment Stats」和「Rollback Segment Summary」重点分析UNXPSTEALCNT、OOS、SSOLDERRCNT三类计数,并结合DBA_HIST_ACTIVE_SESS_HISTORY定位高消耗SQL,而非盲目扩容。
ora-30036 报错出现时,undo 表空间大概率已耗尽或长期被长事务占满;仅靠临时扩容治标不治本,必须结合 awr 报告定位真实瓶颈。
怎么看 AWR 里 UNDO 相关的关键指标
AWR 报告中「Undo Segment Stats」和「Rollback Segment Summary」两个章节直接反映回滚段压力。重点不是看“用了多少 MB”,而是看三类计数:
-
UNXPSTEALCNT(不可扩展段被强制覆盖次数)> 0:说明undo_retention设置失效,旧 undo 被新事务挤掉,极易触发ORA-01555 -
OOS(Out of Space,空间不足计数)持续上升:确认是物理空间真的不够,而非参数配置不合理 -
SSOLDERRCNT(快照过旧错误计数)非零:说明查询一致性读失败,通常伴随高并发长查询或低undo_retention
执行 awrrpt.sql 生成报告后,在「Instance Activity Stats」部分搜索 undo 或直接翻到「Undo Statistics」小节即可定位。注意对比两个快照周期间的趋势变化,单次快照的绝对值意义有限。
用 AWR 找出谁在吃 UNDO 空间
AWR 本身不记录具体 SQL,但可通过 DBA_HIST_ACTIVE_SESS_HISTORY 关联回滚段使用与会话行为:
- 查高消耗会话:
SELECT session_id, sql_id, event, p1text, p1 FROM dba_hist_active_sess_history WHERE sample_time > SYSDATE-1 AND event LIKE 'enq: US%' OR event = 'undo segment extension' - 反查对应 SQL:
SELECT sql_text FROM dba_hist_sqltext WHERE sql_id = '<sql_id>'</sql_id> - 重点关注
event为enq: US - contention的行,这是典型的 UNDO 段争用信号
如果发现某 sql_id 长时间出现在多条记录中,且 p1 值稳定(如 144),基本可锁定该语句对应的 undo 段号 —— 再查 v$rollname 就能知道它属于哪个表空间。
ORA-30036 触发时,别急着加数据文件
盲目执行 ALTER TABLESPACE UNDOTBS1 ADD DATAFILE 可能掩盖真正问题:
- 若存在未提交事务,加空间只是延长报错时间,
v$transaction中status='ACTIVE'的记录必须先处理 - RAC 环境下,每个实例有独立 UNDO 表空间,需分别检查
show parameter undo和gv$rollstat - Oracle 12c+ 支持
SHRINK SPACE,但前提是无活跃事务且表空间未启用RETENTION GUARANTEE,否则会报ORA-30013
更稳妥的路径是:先用 AWR 定位峰值时段的 top SQL → 在测试环境复现 → 拆分批量操作、显式加 COMMIT、或改用 BULK COLLECT + FORALL 减少单事务 undo 生成量。
undo_retention 设多少才合理
这个参数不是越大越好,它只定义“理想保留时间”,实际能否达成取决于空间是否充足和是否启用 RETENTION GUARANTEE:
- 查历史最大保留需求:
SELECT MAX(maxquerylen) FROM v$undostat(单位秒),再上浮 20% 作为初始值 - 生产库建议设为
1800(30 分钟)起步,但若报表作业最长运行 2 小时,就得设成7200 - 启用
RETENTION GUARANTEE后,即使空间紧张也不会覆盖未过期 undo,但会直接导致ORA-30036,慎用
最常被忽略的是:undo_retention 修改后需配合 AWR 中 UNXPSTEALCNT 是否归零来验证效果,而不是只看参数值变了没。


















