ora-30036或innodb undo表空间满是硬性资源瓶颈,需先区分数据库类型:oracle查dba_tablespace_usage_metrics(used_percent≥95%)及v$transaction中used_ublk>10000且start_time超30分钟的长事务;mysql查history list length(>5000即危险)和innodb_undo_log_truncate状态;禁用fast_start_parallel_rollback后再kill;批量delete必须分批(如每5000行commit),避免单事务undo暴涨。

ORA-30036 或 InnoDB: Undo tablespace is full 在大型 DELETE 过程中出现,说明事务已超出 UNDO 容量承载能力——这不是“稍等就好”,而是必须立即干预的资源硬瓶颈。直接 KILL 会触发回滚,反而让系统更卡;盲目调大 UNDO_RETENTION 或扩容表空间,常治标不治本。
查清到底是 Oracle 还是 MySQL 的 UNDO 压力
两者机制完全不同,混用方案会出事:
- Oracle 报
ORA-30036:重点看DBA_TABLESPACE_USAGE_METRICS中used_percent ≥ 95%,再关联V$TRANSACTION找USED_UBLK > 10000且START_TIME超 30 分钟的长事务 - MySQL 报
Undo tablespace is full:查SHOW ENGINE INNODB STATUS里的HISTORY LIST LENGTH,持续 > 5000 就危险;同时确认innodb_undo_log_truncate是否生效(若为OFF或被长事务阻塞,则扩容无效)
别急着 KILL,先关并行回滚防雪崩
已运行 20+ 小时的 DELETE,KILL SESSION 后默认启用 fast_start_parallel_rollback=LOW,可能瞬间拉满 CPU 和 I/O。必须提前降级:
- 查当前设置:
SHOW PARAMETER fast_start_parallel_rollback - 禁用并行回滚:
ALTER SYSTEM SET fast_start_parallel_rollback=FALSE SCOPE=BOTH - 确认生效后再
ALTER SYSTEM KILL SESSION 'sid,serial#',否则回滚过程本身就会压垮系统
分批 DELETE 比“一次性删完”更可靠
单事务删 50 万行,UNDO 不是按行存,而是按块前镜像存——极易爆满。分批不是妥协,是绕过 UNDO 瓶颈的实操路径:
- Oracle:用
ROWID分片 + 显式COMMIT,例如每 5000 行提交一次:DELETE FROM t WHERE rowid IN (SELECT rowid FROM t WHERE ... AND ROWNUM - MySQL:改用
WHERE id BETWEEN x AND y分段,配合SELECT ... FOR UPDATE避免幻读,每次处理 ≤ 1 万行 - 通用原则:避免在循环里累积 DML 后统一提交;更忌在存储过程中隐式开启事务后调外部接口——超时就卡死整个 UNDO 链路
删不动时,用 CTAS + RENAME 绕过 UNDO
当表只是测试数据、无业务强依赖,且 DELETE 已卡死,最稳方案是绕开 UNDO 逻辑:
- 把要保留的数据导出:
CREATE TABLE t_keep AS SELECT * FROM t WHERE keep_condition -
RENAME原表,再RENAME新表为原名 - 重建索引、约束、统计信息——全程不走 UNDO,也不锁全表
- 注意:操作前备份原表 DDL,检查是否有
INVALID对象(SELECT owner, object_name, status FROM dba_objects WHERE status = 'INVALID')
最难处理的从来不是参数或空间,而是那些没显式 COMMIT、却在应用层开着事务等 HTTP 响应的“幽灵连接”——它们不报错,但会让 UNDO 永远无法复用。










