开启innodb_undo_log_truncate=on仅触发逻辑截断(重置lsn、清空页数据、标记可复用),不会调用ftruncate()缩小物理文件尺寸,因此ls -lh看到的undo文件大小不变是正常设计行为;真正释放磁盘空间必须执行“新增undo表空间→设旧表空间为inactive→purge完成→drop”完整流程。

为什么 SET GLOBAL innodb_undo_log_truncate = ON 后文件大小没变
这不是配置失败,是 InnoDB 的设计行为:开启 innodb_undo_log_truncate 仅触发逻辑截断(重置 LSN、清空页内数据、标记空间可复用),**不会调用 ftruncate() 缩小物理文件尺寸**。你执行 ls -lh undo_001.ibu 看到的仍是原始大小,属于正常现象。
- 常见误判:看到文件没缩,就反复改配置、重启 mysqld,结果毫无作用
- 真正释放磁盘空间必须走“设 inactive → purge 完成 → DROP”流程,跳步必卡死
- 注意:8.0 默认的
innodb_undo_001和innodb_undo_002是系统保护表空间,不能直接DROP,必须先添加第三个
如何检查当前 undo 表空间是否满足自动截断前提
别只查变量,要查实时状态。四个硬性条件缺一不可,MySQL 会静默跳过截断逻辑:
-
innodb_undo_tablespaces ≥ 2:运行SHOW VARIABLES LIKE 'innodb_undo_tablespaces';,值为 0 或 1 就不满足 -
innodb_max_undo_log_size > 0:默认 1024(MB),设为 0 直接禁用截断 - 至少一个 undo 表空间的
TRUNCATE_STATUS为truncate_ready:查SELECT NAME, TRUNCATE_STATUS FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE 'undo%'; - 无长事务阻塞:执行
SELECT trx_id, trx_started, trx_rows_modified FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5;,排查运行超 300 秒或修改行数 > 10000 的事务
怎样安全新增 undo 表空间并轮转旧文件
这是释放磁盘空间唯一可行路径。MySQL 要求始终保留 ≥ 2 个 active undo 表空间,所以必须先加再减:
- 创建新表空间:
CREATE UNDO TABLESPACE undo_003 ADD DATAFILE 'undo_003.ibu';(注意后缀必须是.ibu,名称不能以innodb_开头) - 等待 purge 推进:监控
SHOW ENGINE INNODB STATUS\G中的HISTORY LIST LENGTH,降到 500 以下才稳妥 - 设旧表空间为 inactive:
ALTER UNDO TABLESPACE innodb_undo_001 SET INACTIVE; - 确认状态变为
INACTIVE后再DROP:DROP UNDO TABLESPACE innodb_undo_001; - 若需彻底清理,且业务允许停机:导出数据 → 初始化新实例(配好
innodb_undo_tablespaces = 2)→ 导入
哪些操作看似合理实则危险或无效
这些动作在生产环境极易引发故障,务必避开:
- 直接
rm -f /var/lib/mysql/undo_001.ibu:实例重启报错Cannot find undo tablespace,无法启动 - 执行
ALTER TABLESPACE undo_001 ENGINE=InnoDB:语法合法但无任何效果,日志静默,文件大小纹丝不动 - 只改
innodb_undo_directory不重启:新 undo 表空间落到新路径,旧文件仍卡在原目录,且无法迁移 - 对只有两个 undo 表空间的实例执行
SET INACTIVE:报错ERROR 3655 (HY000): Cannot set undo tablespace inactive since there would be less than 2 undo tablespaces left active
DROP UNDO TABLESPACE 这一步——但它依赖前面所有状态检查和 purge 推进,漏掉任何一个环节,DROP 就会卡住或失败。











