undo表空间使用率长期高于90%的主因是tuned_undoretention被自动调优机制异常拉高,导致大量unexpired区段无法回收;需通过dba_undo_extents查status分布及v$undostat验证tuned_undoretention是否超限。

UNDO表空间使用率长期高于90%,基本不是空间真不够,而是Oracle自动调优机制把 tuned_undoretention 拉得太高,导致大量 UNEXPIRED 区段无法回收——这是10g及以上版本最常见的根因。
查清真实占用类型:别只看总使用率
直接执行以下查询,重点看 STATUS 分布:
SELECT status, COUNT(*) cnt, ROUND(SUM(bytes)/1024/1024, 2) mb FROM dba_undo_extents WHERE tablespace_name = (SELECT UPPER(value) FROM v$parameter WHERE name = 'undo_tablespace') GROUP BY status ORDER BY status;
关键判断点:
- 如果
ACTIVE占比高 → 说明有长事务未提交,需查v$transaction和对应v$session - 如果
UNEXPIRED占比远高于EXPIRED(比如 >80%)→ 典型的自动调优失控,tuned_undoretention被抬得过高 - 如果
EXPIRED已占多数但空间仍不释放 → 可能是数据文件未启用自动扩展,或表空间被锁死
检查 tuned_undoretention 是否异常膨胀
运行:
SELECT MAX(tuned_undoretention) max_tuned, MAX(maxquerylen) max_query_sec FROM v$undostat WHERE begin_time > SYSDATE - 1;
常见陷阱:
-
max_tuned超过 86400(24小时)甚至到数百万秒 → 这是Oracle根据表空间大小反向推算的结果,和业务实际需求完全脱钩 -
max_query_sec很小(比如 max_tuned 却极大 → 基本可断定是自动调优 bug,尤其在非自动扩展的数据文件上更易触发 - 该值在 RAC 环境中各节点可能不同 → 需分别查
gv$undostat,节点间差异大说明负载分布不均或某节点存在隐式长事务
快速止血:关闭自动调优并重设 retention
这不是权宜之计,而是最稳妥的生产操作。执行前确认:
- 数据库版本 ≥ 10.2.0.4(推荐),或已打补丁
420525.1 - 应用无强依赖超长闪回查询(如要求保留7天以上历史数据)
操作步骤:
ALTER SYSTEM SET "_undo_autotune" = FALSE SCOPE=BOTH; ALTER SYSTEM SET undo_retention = 3600 SCOPE=BOTH; -- 建议从 1 小时起步,后续按业务最长查询时间微调
注意:
- 修改后不会立即释放空间,需等待现有
UNEXPIRED区段自然过期(按新undo_retention计时) - 若想加速释放,可配合收缩数据文件(仅限自动扩展已开启且有足够空闲空间时):
ALTER DATABASE DATAFILE '<path>' RESIZE <smaller_size>M;</smaller_size></path> - 切勿在
UNEXPIRED仍占主导时直接DROP TABLESPACE—— 报错ORA-30013是必然结果
真正释放空间前必须确认的两件事
即使调低了 undo_retention 并关掉了自动调优,空间也不会“立刻”回来。你必须等:
-
DBA_UNDO_EXTENTS.STATUS中UNEXPIRED逐步转为EXPIRED→ 这个过程受新 retention 值约束,不是命令一敲就完事 -
dba_free_space显示对应表空间出现可用块 → 才代表 Oracle 认为这部分空间可复用
最容易被忽略的是:很多 DBA 查到 EXPIRED 上升就以为搞定,却没盯住 dba_free_space 是否同步增长。如果没涨,说明 undo segment 的 extent 还没被标记为可重用,此时强行 shrink 或新增数据文件都只是掩盖问题。











