ora-01555根因在主库undo管理不当:需设undo_retention≥v$undostat.maxquerylen的1.5倍、启用retention guarantee,并确保undo表空间autoextend开启且空间充足;备库无法自行解决,唯一可控动作是收窄查询窗口。

ADG备库ORA-01555根子永远在主库
备库自己没undo表空间,也不存历史UNDO块——它只靠主库产生的UNDO记录(随归档/实时日志传过来)做一致性读。一旦主库把某个SCN的UNDO覆盖了,备库查到那个点就必然报ORA-01555。改备库参数、清缓存、重启实例全无效。
必须确认两件事是否已在主库生效:
-
UNDO_RETENTION设为v$undostat.maxquerylen的1.5倍以上(比如查出最大值是2200秒,就设3600) -
RETENTION GUARANTEE已启用:ALTER TABLESPACE undotbs1 RETENTION GUARANTEE(undotbs1替换成实际UNDO表空间名)
查主库UNDO真实压力:别信dba_free_space
dba_free_space对UNDO表空间完全失真,它不反映UNEXPIRED块占用情况。真正要看的是:
- 当前最长查询耗时:
SELECT MAX(maxquerylen) FROM v$undostat - UNDO空间是否被未过期块挤满:
SELECT tablespace_name, status, SUM(bytes)/1024/1024 mb FROM dba_undo_extents GROUP BY tablespace_name, status—— 若UNEXPIRED占比长期>95%,说明空间撑不住 - AUTOEXTEND是否开着:
SELECT file_name, autoextensible, maxbytes/1024/1024 max_mb FROM dba_data_files WHERE tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace')——autoextensible为NO必须立刻改
开了RETENTION GUARANTEE却报ORA-30036?那是好事
ORA-30036(无法扩展UNDO段)比ORA-01555更明确:说明RETENTION GUARANTEE生效了,但物理空间不够。这时不能关GUARANTEE去“换回”ORA-01555,而应立刻扩容:
- 先执行:
ALTER DATABASE DATAFILE '/u01/oradata/DB/undotbs01.dbf' AUTOEXTEND ON NEXT 100M MAXSIZE 10G(路径以查询结果为准) - 再确认UNDO表空间总大小足够支撑峰值:
(UNDO_BLOCK_PER_SEC × maxquerylen) + 安全余量,其中UNDO_BLOCK_PER_SEC可从v$undostat估算
Oracle 12c起还多一层风险:INM(In-Memory Undo)若启用,会额外消耗内存池中的UNDO缓冲,需同步检查inmemory_undo参数是否为TRUE并评估影响。
备库侧唯一可控动作:收窄查询窗口
你没法改主库?那就只能从SQL端卡住风险点。长查询时间越久,所需的历史SCN越老,撞上被覆盖UNDO的概率指数上升:
- 禁用无WHERE的全表扫描,尤其对>1GB的大表
- 避免未绑定变量的长SQL(硬解析+执行计划抖动会拉长一致性读链)
- 对已知慢查询,加
/*+ OPT_PARAM('_serial_direct_read' 'never') */防止跳过buffer cache中CR块(仅权宜) - 最可靠做法:
DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER显式指定一个较新的SCN,把一致性读窗口缩到分钟级
真正容易被忽略的是:TUNED_UNDORETENTION这个自动调优值可能远低于maxquerylen,尤其在低负载时段。它不等于你设的UNDO_RETENTION,必须用SELECT MAX(tuned_undoretention) FROM v$undostat核对。











