ORA-01555在11g RAC中主因是UNDO空间实际可用性不足,需先查真实使用率、expstealcount及跨节点长事务,再结合tuned_undoretention评估是否扩容或调参,分片处理比盲目调参更可靠。
ora-01555在11g rac里不是“undo_retention设小了”就能调好的问题,核心是undo空间实际可用性跟不上长查询需求——盲目调高undo_retention反而加速报错。
查当前UNDO压力是否已爆满
先别急着改参数。RAC环境下各节点共享UNDO表空间,但v$undostat只反映本实例历史,必须交叉验证:
- 查UNDO表空间真实使用率:
SELECT tablespace_name, ROUND((bytes - free_bytes)/1024/1024) AS used_mb FROM dba_data_files d, (SELECT tablespace_name, NVL(SUM(bytes), 0) free_bytes FROM dba_free_space GROUP BY tablespace_name) f WHERE d.tablespace_name = f.tablespace_name AND d.tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace'); - 看有没有“偷块”行为:
SELECT MAX(expstealcount) FROM v$undostat;若值 > 0,说明UNDO空间已不够用,系统正在强制覆盖未过期块——此时调undo_retention毫无意义 - RAC需额外检查:各节点
v$transaction中是否有长期未提交事务(start_time早于10分钟前且used_ublk> 50000),这类事务会锁住大量UNDO块,影响全局
扩容UNDO表空间必须启用AUTOEXTEND
11g RAC默认UNDO表空间常为固定大小,这是ORA-01555高频触发的主因。手动加文件不如直接开自动扩展:
- 确认当前数据文件路径:
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/to/undotbs01.dbf' AUTOEXTEND ON NEXT 200M MAXSIZE 8G;(路径务必与上一步查出的一致) - 不建议新增数据文件——RAC中多节点争用同一UNDO表空间时,新增文件可能加剧空间碎片,且无法解决“块被抢”本质问题
调undo_retention前先看v$undostat.tuned_undoretention
Oracle会根据负载动态调整实际保留窗口,tuned_undoretention才是真实生效值。硬设undo_retention超过它,只会让UNDO块压得更久、空间更快耗尽:
- 查最近1小时趋势:
SELECT begin_time, tuned_undoretention, maxquerylen FROM v$undostat WHERE begin_time > SYSDATE - 1/24 ORDER BY begin_time DESC; - 若
maxquerylen持续 >tuned_undoretention(比如前者是7200秒,后者仅1800),说明当前UNDO空间已无力支撑现有查询负载,优先扩容而非调参 - 仅当
tuned_undoretention稳定在合理范围(如3600~7200)、且expstealcount=0时,才考虑设undo_retention为略高于maxquerylen的值,例如:ALTER SYSTEM SET undo_retention = 10800 SCOPE=BOTH;
对expdp或长报表SQL,分片比调参更可靠
RAC中导出大表或跑跨节点JOIN报表时,单次扫描动辄几十分钟,靠UNDO参数兜底风险极高。分片处理可绕过一致性读瓶颈:
- expdp导出含LOB的大表:加
QUERY参数按主键分段,例如QUERY=employees:"WHERE employee_id BETWEEN 1 AND 100000",配合并行作业调度 - 报表SQL优化:避免
SELECT * FROM big_table全扫,改用ROWID分批,例如SELECT * FROM t WHERE rowid IN (SELECT rowid FROM t WHERE rownum ,再循环取下一批 - 切记:分片后每批次事务时间应控制在
tuned_undoretention的1/3以内,否则仍可能踩中覆盖窗口
最易被忽略的一点:RAC中undo_management=AUTO是强制要求,但部分老环境残留undo_suppress_errors=TRUE等隐式参数,会导致v$undostat指标失真。遇到调参无效时,先用SHOW PARAMETER undo核对所有相关参数是否处于预期状态。


















