ORA-01555本质是查询所需的一致性读镜像被覆盖,主因是UNDO_RETENTION与实际空间不足的矛盾;需优先扩容UNDO表空间并启用AUTOEXTEND,再合理调参,对长查询应分片处理而非盲目延长保留时间。
ORA-01555报错本质是UNDO数据被覆盖,不是“回滚段太小”那么简单
ora-01555报错真正含义是:查询启动时需要的旧版本数据(一致性读镜像),在执行过程中已被其他事务覆盖——不是undo表空间没空间了,而是“该留的镜像没留住”。关键变量是undo_retention与实际undo空间可用性之间的张力。
常见错误现象包括:长SQL中途失败、ETL任务在凌晨跑一半报错、全量迁移卡在某张大表、FineBI或OMS同步突然中断并抛出ORA-01555: snapshot too old。
-
UNDO_RETENTION只是“建议保留时长”,不是硬保证;实际能否保留住,取决于UNDO表空间是否足够、是否有空闲块可重用 - 当UNDO表空间使用率长期100%,哪怕
UNDO_RETENTION=3600,也可能连5分钟前的镜像都保不住 - 手动设置
undo_management=MANUAL已过时,10g+必须用AUTO,否则CREATE ROLLBACK SEGMENT会报错
调高UNDO_RETENTION前先确认UNDO表空间是否真有扩容余地
盲目把UNDO_RETENTION从900秒调到7200秒,可能让问题更糟:UNDO数据压得更久,空间更快耗尽,反而加速覆盖——尤其当UNDO表空间本身是固定大小且无自动扩展时。
实操建议分三步走:
- 查当前UNDO使用压力:
SELECT tablespace_name, status, sum(bytes)/1024/1024 AS mb FROM dba_undo_extents GROUP BY tablespace_name, status;,重点关注EXPIRED占比是否极低、UNEXPIRED是否持续高位 - 确认UNDO表空间是否启用了
AUTOEXTEND: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'); - 若未启用自动扩展,优先执行:
ALTER DATABASE DATAFILE '<undo_file_path>' AUTOEXTEND ON NEXT 100M MAXSIZE 10G;,再考虑调UNDO_RETENTION
对迁移/导出类场景,比调参更有效的其实是切分查询
比如OMS或DWS迁移时扫全表报ORA-01555,根源常是单次扫描耗时远超UNDO_RETENTION。此时调参治标,切分治本。
典型做法(以按主键分片为例):
- 先估算表行数:
SELECT num_rows FROM dba_tables WHERE owner='SCHEMA' AND table_name='T_BIG'; - 按
ROWID或主键范围分批次拉取,例如每次10万行:SELECT * FROM t_big WHERE id BETWEEN :start_id AND :end_id; - 避免
ORDER BY ... OFFSET ... FETCH NEXT——它仍需全扫描排序,一致性读压力不减;改用闭区间谓词+索引驱动 - 如用Data Pump,加
QUERY="WHERE rownum <= 100000"参数虽简单,但无法跳过已取部分,需配合PL/SQL动态生成多个dump文件
某些Oracle版本需额外打补丁或设隐含参数
Oracle 11.2.0.4+及部分12c环境,即使UNDO配置合理,LOB字段或延迟块清除场景仍可能触发ORA-01555。这不是配置错了,而是已知缺陷。
此时需检查MOS文档ID 11814428.1,对应修复方案为:
- 确认是否命中该Bug(表现为错误中含
_SYSSMU回滚段名且伴随LOB访问) - 临时规避(生产慎用):
ALTER SYSTEM SET "_FIX_CONTROL" = "11814428:0" SCOPE=BOTH SID='*'; - 长期解法仍是升级至11.2.0.4 BP30或更高版本,该参数在19c后默认关闭
别忽略STATUS=ACTIVE的UNDO区——它表示事务还没提交,这部分空间永远不可重用,哪怕UNDO_RETENTION再大也救不了。如果大量短事务频繁commit,反而比少数长事务更容易推高ACTIVE占比,这点和直觉相反。

















