ORA-01555主因是查询所需一致性读镜像被覆盖,取决于UNDO_RETENTION与实际Undo空间可用性的共同作用;需先查最长查询耗时、UNEXPIRED占比及AUTOEXTEND状态,再按安全公式(MAXQUERYLEN×1.5)合理设参。
ora-01555 和 undo 表空间大小没有直接因果关系;报错主因是查询所需的一致性读镜像(即某个 scn 时刻的旧数据)被覆盖,而是否被覆盖,取决于 undo_retention 设置与实际 undo 空间可用性的共同作用——不是“表空间小就一定出错”,也不是“表空间大就永不报错”。
查清当前 Undo 压力到底在哪
别急着扩容或调参,先确认问题真实来源:
- 查最长查询耗时:
SELECT MAX(maxquerylen) FROM v$undostat—— 若返回值远超当前UNDO_RETENTION(比如 2800 秒 vs 900 秒),说明快照窗口根本不够用 - 看 Undo 空间是否真满:
SELECT tablespace_name, ROUND(SUM(bytes)/1024/1024) mb_used FROM dba_undo_extents WHERE status = 'UNEXPIRED' GROUP BY tablespace_name—— 如果UNEXPIRED占比长期 >95%,且EXPIRED接近 0,说明空间紧张、旧块被强占 - 检查自动扩展是否启用:
SELECT autoextensible, maxbytes/1024/1024 max_mb FROM dba_data_files WHERE tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace')—— 若autoextensible = 'NO',再大的UNDO_RETENTION都会失效
调整 UNDO_RETENTION 前必须满足的条件
UNDO_RETENTION 是 soft limit,Oracle 只在空间充足时尽力遵守。盲目调高反而可能加速覆盖:
- 必须先确保 Undo 表空间已启用
AUTOEXTEND ON,且MAXSIZE足够(建议至少预留 1.5 倍峰值需求) - 若数据库启用了
RETENTION GUARANTEE,则需额外确认:该参数会让 Oracle 强制保留到期前的 undo,但一旦空间耗尽,新事务会直接失败(ORA-30036),风险更高 - 安全值估算公式:
UNDO_RETENTION ≈ 最近7天最大 <code>maxquerylen× 1.5(例如最长查询 22 分钟 → 设为 2000 秒)
expdp / 物化视图 / 存储过程里最易踩的坑
这三类场景看似都报 ORA-01555,但根因和解法完全不同:
-
expdp 导出中断:本质是单次全表扫描耗时过长。优先用
FLASHBACK_SCN或分片导出(如QUERY="WHERE id BETWEEN :1 AND :2"),而不是调UNDO_RETENTION -
物化视图刷新失败:90% 源于用了
COMPLETE刷新。改用FAST ON COMMIT并确认DBMS_MVIEW.EXPLAIN_MVIEW返回fast_refreshable = 'YES',可将一致性窗口从小时级压缩到秒级 -
存储过程游标报错:OPEN 一瞬即锁定 SCN,后续 FETCH 全依赖该快照。避免隐式长游标,改用
FOR rec IN (SELECT ...)循环,或加ROWID范围条件分页,把单次 OPEN 时间压到几秒内
真正容易被忽略的是:Undo 空间是否碎片化、是否存在未提交的长事务、以及 OLTP 和 OLAP 是否共用同一 Undo 表空间。这些不会直接体现在参数里,但会彻底瓦解任何参数调整的效果。


















