ora-30036错误本质是oracle undo表空间物理耗尽或被长事务锁死,需立即查dba_tablespace_usage_metrics确认used_percent≥95%,关联v$transaction与v$session识别used_ublk>10000且start_time超30分钟的长事务,优先添加自动扩展数据文件扩容,并分批提交批量dml。
java 应用报 ora-30036: unable to extend segment by x in undo tablespace 'undotbs1',本质不是 java 代码问题,而是 oracle 的 undo 表空间已满、无法为当前 dml 分配回滚段空间。必须从数据库侧干预,java 层最多只能做规避或降级。
查 UNDO 表空间真实使用率,别信“空闲空间”假象
很多 DBA 看 DBA_FREE_SPACE 发现还有几百 MB 就以为够用,但实际可能已无法分配新 undo 段 —— 因为 undo 段需要连续空间,且受 undo_retention 和未提交事务拖累。
- 运行这个语句看实时占用率(单位:GB):
SELECT tablespace_name, ROUND(used_space*8192/1024/1024, 2) AS used_mb, ROUND(tablespace_size*8192/1024/1024, 2) AS total_mb, ROUND(used_percent, 2) AS used_pct FROM dba_tablespace_usage_metrics WHERE tablespace_name LIKE 'UNDO%';
-
used_pct > 95%是危险信号;used_pct = 100且持续不下降,说明有长事务或未提交会话卡住 undo 段 - 同时查活跃事务:
SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, t.used_ublk, t.start_time, sq.sql_text FROM v$transaction t JOIN v$session s ON t.ses_addr = s.saddr LEFT JOIN v$sql sq ON s.sql_id = sq.sql_id ORDER BY t.used_ublk DESC;
重点关注used_ublk > 10000或start_time超过 30 分钟的会话
紧急扩容:优先用 autoextend,别硬 resize
如果磁盘还有空间,最快速有效的是启用自动扩展,而不是手动 resize —— 后者可能因文件系统碎片失败,且不能解决后续增长问题。
- 确认数据文件路径和当前大小:
SELECT file_name, bytes/1024/1024 AS mb, autoextensible FROM dba_data_files WHERE tablespace_name = 'UNDOTBS1';
- 开启自动扩展(示例扩到 32G 上限):
ALTER DATABASE DATAFILE '/u01/oradata/ORCL/undotbs01.dbf' AUTOEXTEND ON NEXT 512M MAXSIZE 32G;
- 如果当前文件已满且
AUTOEXTENSIBLE = 'NO',先开 autoextend 再执行一次RESIZE通常比直接 resize 更稳 - 注意:
MAXSIZE UNLIMITED在某些存储(如 ASM)或策略下不被允许,需按实际环境设上限
Java 层能做的只有三件事:切分、超时、兜底
Java 无法释放 undo 空间,但可以避免加剧问题:
- 批量写入必须分页提交:把
INSERT /*+ APPEND */ INTO ... SELECT ...改成每次最多 1000–5000 行 +connection.commit();否则单事务撑爆 undo - 设置 JDBC 事务超时(Spring 中用
@Transactional(timeout = 30)),防止应用层卡死导致事务长期挂起 - 捕获
SQLException并判断getSQLState().equals("72000") && getErrorCode() == 30036,触发降级逻辑(如写本地队列、告警、跳过) - 禁用连接池的“testOnBorrow”对 undo 敏感操作(如 Druid 的
validationQuery=SELECT 1 FROM DUAL本身不耗 undo,但频繁校验可能干扰长事务)
真正治本:换 UNDO 表空间 + 调参
如果扩容后一周内反复报警,说明当前 UNDO 设计不合理,必须重构:
- 建新 UNDO 表空间(带 autoextend):
CREATE UNDO TABLESPACE undotbs2 DATAFILE '/u01/oradata/ORCL/undotbs02.dbf' SIZE 4G REUSE AUTOEXTEND ON NEXT 1G MAXSIZE 64G;
- 切换并验证:
ALTER SYSTEM SET undo_tablespace = 'UNDOTBS2' SCOPE=BOTH; SHOW PARAMETER undo_tablespace;
- 调高
undo_retention到 10800(3 小时)前,先确认V$UNDOSTAT.TUNED_UNDORETENTION是否长期低于该值 —— 如果是,说明物理空间撑不住,强行调高只会加速ORA-30036 - 旧 UNDO 表空间等所有段 offline 后再删:
SELECT segment_name, status FROM dba_rollback_segs WHERE tablespace_name = 'UNDOTBS1'; -- 全为 OFFLINE 才安全 DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;
UNDO 不足从来不是孤立问题:它背后往往是 Java 批处理没分页、定时任务卡死、或 DBLINK 查询未提交。光扩空间只是止血,得顺着 v$transaction 和应用日志找到那个“不动的事务”,才算真正闭环。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











