innodb_undo_log_truncate 是启用 undo 表空间自动截断的开关,但仅当配置多个独立 undo 表空间(≥2)、系统非只读、且存在已 purge 完毕的 undo 段时才生效;单 ibdata1 无效,需停库重建拓扑并重启。

innodb_undo_log_truncate 是什么,开了就有用吗
innodb_undo_log_truncate 只是一个开关,开启后不会立即收缩 undo log,而是允许 InnoDB 在满足条件时**自动触发截断(truncate)undo tablespace 文件**。它依赖一整套前提:必须有多个独立的 undo 表空间(innodb_undo_tablespaces ≥ 2)、系统处于非只读模式、且存在“可回收”的历史 undo 段(即对应事务已全部 purge 完毕)。如果只有默认的 ibdata1 承载 undo,这个配置完全不生效。
如何正确配置才能让 truncate 生效
关键不是单开一个参数,而是重建 undo 表空间拓扑。MySQL 5.7+ 支持独立 undo 表空间,但**初始化后无法在线切换**,必须重做:
- 停库,备份数据
- 在
my.cnf中设置:innodb_undo_tablespaces = 4(建议 ≥2,偶数更稳妥),innodb_undo_log_truncate = ON,innodb_undo_directory = ./undo(确保目录存在且 MySQL 可写) - 添加
innodb_undo_logs = 128(保持与旧值一致,避免启动失败) - 删除原有
ibdata1和所有undo001… 文件(⚠️仅限测试/新部署环境!生产务必先确认 purge 进度) - 重启 MySQL,会自动生成新的独立 undo 文件(如
undo001~undo004)
truncate 实际触发时机和监控方法
InnoDB 每 128 秒检查一次是否满足 truncate 条件,真正执行需同时满足:
-
innodb_purge_rseg_truncate_frequency≥ 1(默认 128,单位为 purge loop 次数) - 至少有一个 undo 表空间的 rseg 使用率 TRX_RSEG_HISTORY_SIZE 很小)
- 当前无长事务或未 purge 的历史记录堆积(查
SELECT * FROM information_schema.INNODB_TRX和SHOW ENGINE INNODB STATUS中 HISTORY LIST 大小)
观察是否生效,看错误日志是否有类似 [Note] InnoDB: Truncating tablespace ...;也可定期检查 ls -lh undo/ 文件大小变化。
为什么 truncate 后文件没变小?
这是最常被误解的一点:InnoDB 的 truncate 操作只是将表空间**逻辑标记为空闲并重置 LSN**,底层文件尺寸**不会自动缩小**。操作系统层面的文件大小保持不变,除非你手动执行 OPTIMIZE TABLESPACE(MySQL 8.0.30+)或导出/重建 undo 表空间。所以磁盘空间不会立刻释放——这不是配置错了,是设计如此。若急需回收空间,只能停库后用 innodb_undo_tablespaces 配合重建流程彻底替换。


















