undo表空间无法直接收缩,因active/unexpired回滚段区块不可迁移压缩;仅支持在线扩展(添加文件或扩展现有文件),收缩依赖自动回收且受长事务阻塞。
undo 表空间不能像普通表空间那样直接 alter tablespace ... resize,因为它的数据文件由 oracle 自动管理段(auto segment management),且活跃回滚段(active)会阻塞物理收缩。真正能“在线调整大小”的,只有扩展(加文件或扩现有文件),而收缩需依赖空间回收机制自动完成——前提是没长事务卡住。
为什么不能直接 shrink UNDO 表空间?
Oracle 不允许对 UNDOTBS1 执行 ALTER DATABASE DATAFILE ... RESIZE 到更小值,报错 ORA-03297:文件包含超出请求尺寸的使用数据。这不是权限或语法问题,而是底层设计限制:ACTIVE 和 UNEXPIRED 区块必须保留在原位置,无法迁移压缩。
-
DBA_UNDO_EXTENTS中STATUS = 'ACTIVE'的区块,只要对应事务未提交或未回滚,就永远不能被移动或释放 -
STATUS = 'UNEXPIRED'的区块是否可回收,取决于undo_retention和实际空间压力;即使设了AUTOEXTEND ON,Oracle 也不会主动把已分配空间还给操作系统 - 试图用
ALTER DATABASE DATAFILE ... AUTOEXTEND OFF再手动 shrink,只会让后续空间耗尽更快,不解决根本问题
在线扩展 Undo 表空间的两种安全方式
扩展是唯一真正在线、无锁、不影响业务的操作。但要注意路径、权限和自动扩展策略。
- 添加新数据文件(推荐):
ALTER TABLESPACE UNDOTBS1 ADD DATAFILE '/u01/oradata/DB19C/undotbs02.dbf' SIZE 2G AUTOEXTEND ON NEXT 256M MAXSIZE 8G;
必须确保目标路径有足够磁盘空间,且 Oracle 用户对该目录有写权限;MAXSIZE建议设上限,防止单个文件撑爆文件系统 - 扩展现有文件(谨慎):
ALTER DATABASE DATAFILE '/u01/oradata/DB19C/undotbs01.dbf' AUTOEXTEND ON NEXT 128M MAXSIZE 4G;
若该文件已接近文件系统上限,扩大会失败;执行前先df -h确认剩余空间 ≥ 预期增长量 - 两者都无需重启实例,也不需要
ALTER SYSTEM SWITCH UNDO TABLESPACE,Oracle 会自动将新分配的区用于新事务
长事务期间,扩展后空间仍不释放?查这三个地方
扩展只是“兜底”,不是根治。如果刚加完 2G 文件,DBA_UNDO_EXTENTS 里 EXPIRED 仍是 0%,说明空间被卡死,不是不够,而是出不来。
- 运行:
SELECT s.sid, s.serial#, s.username, s.status, t.start_time, t.used_ublk FROM v$session s JOIN v$transaction t ON s.saddr = t.ses_addr WHERE t.start_time 重点看 <code>STATUS = 'INACTIVE'</code> 的会话——它们挂着连接却不提交,比 <code>ACTIVE</code> 更危险
- 检查
V$UNDOSTAT近 1 小时的MAXCONCURRENCY是否持续 ≥ 20:高并发争抢回滚段头,会导致UNXPSTEALCNT上升,间接拖慢空间回收 - 确认
undo_retention是否被设为极端值(如86400)且UNDOTBS1没开AUTOEXTEND:此时 Oracle 宁可报ORA-30036也不敢覆盖UNEXPIRED区,调低 retention 比加文件更有效
真正的难点从来不在“怎么加空间”,而在于识别那些 INACTIVE 却持有 used_ublk > 10000 的会话——它们安静地躺在连接池里,吃掉所有新增容量。











