ORA-01555错误主因是undo表空间不足而非_UNDO_RETENTION设置过小;该参数仅为建议值,实际保留时长由空闲空间决定,空间紧张时旧undo会被强制覆盖。
undo retention 参数本身不会直接“耗尽空间”,但当它与自动调优机制、表空间配置和实际负载不匹配时,会触发空间失控式增长——根本原因是 oracle 在空间压力下仍强行保留未过期 undo 块,而非按预期回收。
UNDO_RETENTION 不是硬约束,而是“建议值”
Oracle 只在 undo 表空间有余量时才尽力遵守 UNDO_RETENTION。一旦空间吃紧,它会优先回收 UNEXPIRED 状态的块(即已提交但还没到保留时间的块),哪怕你设了 7200 秒。盲目调高该参数,若表空间不能自动扩展,反而加速空间耗尽。
-
V$UNDOSTAT.TUNED_UNDORETENTION才是真实生效值——它由 MMON 进程每 30 秒根据MAXQUERYLEN动态计算,10g/11g/12c 默认启用自动调优 - 查当前实际值:
SELECT tuned_undoretention, maxquerylen FROM v$undostat WHERE begin_time > SYSDATE - 1/24 ORDER BY begin_time DESC FETCH FIRST 1 ROW ONLY - 若
TUNED_UNDORETENTION比你手动设的值大得多(比如 345600 秒),说明自动调优已接管,UNDO_RETENTION参数已被忽略
_undo_autotune = TRUE 是 10g+ 的默认行为,且难以绕过
从 Oracle 10.2 开始,只要启用自动 undo 管理(undo_management=auto),隐含参数 _undo_autotune 默认为 TRUE,且无法通过常规方式禁用(ALTER SYSTEM SET "_undo_autotune"=FALSE 在某些版本中无效或需重启)。
- 该机制会持续拉高保留时间,尤其当出现长查询(如报表、ETL)后,
MAXQUERYLEN上升 →TUNED_UNDORETENTION被推高 → undo 块长期处于UNEXPIRED状态无法释放 - 在
AUTOEXTENSIBLE = NO的 undo 数据文件上,这会导致空间使用率快速冲向 100%,并伴随V$UNDOSTAT.NOSPACEERRCNT持续增长 - 验证是否被自动调优控制:
SELECT ksppinm, ksppstvl FROM x$ksppi x, x$ksppcv y WHERE x.indx = y.indx AND ksppinm = '_undo_autotune'
空间爆满的真实信号不是“用了多少”,而是“哪些块卡住了”
看 DBA_UNDO_EXTENTS.STATUS 分布比看总使用率更关键:大量 UNEXPIRED + 极少 EXPIRED,说明空间被“冻结”在未过期状态,回收机制失效。
- 执行:
SELECT status, COUNT(*) cnt, ROUND(SUM(bytes)/1024/1024, 2) mb FROM dba_undo_extents GROUP BY status - 若
UNEXPIRED占比超 80% 且EXPIRED接近 0,基本可判定是自动调优 + 空间受限导致的回收停滞 - 此时扩容或开
AUTOEXTEND是最直接解法;否则即使杀掉长事务,UNEXPIRED块也不会立刻变EXPIRED - 临时缓解可用:
ALTER SYSTEM SET "_highthreshold_undoretention" = 3600(限制自动调优上限),但需注意该参数在 12.2+ 中行为可能变化
真正要盯住的不是参数值本身,而是 V$UNDOSTAT.NOSPACEERRCNT 是否非零、DBA_UNDO_EXTENTS 中 UNEXPIRED 是否持续堆积、以及 undo 数据文件是否锁死在 AUTOEXTENSIBLE = NO 状态——这三点没解决,调任何参数都是徒劳。


















