ora-01555根本原因是undo表空间物理空间不足,而非undo_retention设置过小;当autoextensible=no且pct_free长期低于5%时,调大该参数无效,必须优先启用自动扩展或扩容表空间。

UNDO表空间没开自动扩展,调再大UNDO_RETENTION也没用
很多人一见ORA-01555就去改UNDO_RETENTION,结果毫无改善。根本原因是:Oracle只在有空闲空间时才尽力遵守这个参数;一旦undo_tablespace空间吃紧,它会直接覆盖UNEXPIRED状态的undo块——哪怕离到期还差一小时。
必须先确认自动扩展是否启用:
SELECT file_name, autoextensible, maxbytes/1024/1024 AS max_mb FROM dba_data_files WHERE tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace');
- 如果
autoextensible = 'NO',优先执行ALTER DATABASE DATAFILE '<path>' AUTOEXTEND ON NEXT 100M MAXSIZE 10G</path> - 若
max_mb为0或极小(比如2M),说明表空间被建成了固定大小,扩容比调参紧急得多 -
pct_free长期低于5%且autoextensible = 'NO',所有后续操作都是白忙
查V$UNDOSTAT.MAXQUERYLEN比看UNDO_RETENTION更管用
MAXQUERYLEN是过去10分钟内最长查询的实际耗时(秒),它反映系统真实的一致性读压力窗口。这个值才是你设参的唯一可靠依据,不是拍脑袋定的“我猜报表要跑20分钟”。
运行这句定位压力源:
SELECT begin_time, end_time, undoblks, txncount, ssolderrcnt, nospaceerrcnt, maxquerylen FROM v$undostat WHERE begin_time > SYSDATE - 1/24 ORDER BY begin_time DESC;
- 若某行
maxquerylen = 2800(约47分钟),但当前UNDO_RETENTION = 900(15分钟),说明参数早已失效 -
nospaceerrcnt > 0表示空间已开始强制回收未过期undo,是物理空间不足的铁证 -
ssolderrcnt > 0才是ORA-01555发生次数的直接计数,和maxquerylen持续超标强相关
导出、物化视图、游标这三类场景不能只靠调参
它们触发ORA-01555的机制不同,通用调参往往治标不治本:
-
expdp失败:本质是单次全表扫描太长。用QUERY="WHERE id BETWEEN :1 AND :2"分片导出,比把UNDO_RETENTION拉到7200秒更有效 - 物化视图刷新报错:90%源于
COMPLETE刷新。改用FAST ON COMMIT并确认DBMS_MVIEW.EXPLAIN_MVIEW返回fast_refreshable = 'YES' - 存储过程游标报错:
OPEN瞬间就锁定了SCN,后续FETCH全程依赖该快照。避免在循环中FETCH前做耗时操作(如网络调用、日志写入)
设UNDO_RETENTION的安全值不是经验,而是计算
公式:UNDO_RETENTION ≈ MAXQUERYLEN × 1.5(向上取整到百位)。例如最近最大maxquerylen是1326秒,设为2000秒比设成3600更合理。
但这个值生效的前提是:undo表空间能撑住对应量级的活跃undo数据。估算最低空间需求:
SELECT (undoblks * db_block_size * 1.5) / 1024/1024 AS "MB_required" FROM v$undostat, (SELECT value AS db_block_size FROM v$parameter WHERE name = 'db_block_size') WHERE begin_time = (SELECT MAX(begin_time) FROM v$undostat);
- 结果若远超当前undo表空间剩余空间,说明即使参数设对了,物理上也存不住
- 启用了
RETENTION GUARANTEE?务必确认MAXSIZE足够,否则可能引发ORA-30036(事务直接失败) - 别忽略
V$UNDOSTAT.UNDOBLKS突增时段——它常和业务批处理窗口重合,需协同应用方调整执行时间
真正卡住人的从来不是参数名怎么拼,而是搞不清MAXQUERYLEN和UNEXPIRED占比谁在驱动问题;一个没查空间余量就调参,另一个没看nospaceerrcnt就加内存,都容易让问题在凌晨三点准时复现。











