mysql 8.0.23+ 中 set global innodb_undo_directory 仅影响新分配回滚段,旧段元数据已固化于系统表空间且无法重绑定路径,故不生效;必须重启并配合 drop undo tablespace 才能完成物理迁移。

MySQL 8.0 不能真正“在线迁移”已有回滚段到新目录,innodb_undo_directory 的在线修改只对新分配的回滚段生效,旧段仍留在原路径,且不会自动移动或重载。
为什么 SET GLOBAL innodb_undo_directory 不起作用?
你执行 SET GLOBAL innodb_undo_directory = '/data/mysql/undo' 后查 SHOW VARIABLES LIKE 'innodb_undo_directory' 看似变了,但:
- 该变量在 8.0.23+ 才支持动态设置,但仅影响后续新建的 rollback segment —— 已存在的 undo 表空间(如
undo_001)仍绑定原路径 - InnoDB 启动时已将旧段元数据固化在系统表空间或数据字典中,运行时无法重绑定物理文件位置
- 错误日志里若出现
InnoDB: Operating system error number 2 in a file operation,基本就是 mysqld 去旧路径找文件失败
哪些参数能真正在线调整?
只有以下三个与 undo 生命周期管理强相关的变量支持运行时变更,且需满足前提条件:
-
innodb_undo_log_truncate=ON:必须已启用独立 undo 表空间(即innodb_undo_tablespaces >= 2),否则 truncate 逻辑不触发 -
innodb_max_undo_log_size:影响单个 undo 文件触发截断的阈值,设为 0 表示禁用自动截断 -
innodb_purge_rseg_truncate_frequency:控制 purge 线程检查可截断 undo 段的频率(单位为 purge 操作次数,默认 128)
注意:innodb_undo_tablespaces 和 innodb_undo_logs 是只读变量,修改需重启;innodb_undo_directory 动态设置后,必须等旧段自然释放(对应事务全部提交/回滚 + purge 完成)才可能被新段替代。
如何确认新配置是否实际生效?
别只信 SHOW VARIABLES,重点看磁盘和数据字典:
- 执行
SELECT NAME, PATH FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE 'undo%',确认PATH列是否指向新目录 - 检查
ls -l /data/mysql/undo/是否有新生成的undo_003.ibu(8.0.14+ 动态创建的文件以.ibu结尾) - 若仍看到旧
undo_001在原数据目录下,说明它尚未被 purge 线程回收 —— 此时即使配置了新目录,也不会“切换”过去
真正要换目录,只能分两步走
所谓“在线”,本质是“避免停机太久”,但无法跳过物理迁移环节:
- 第一步:在 my.cnf 中写死
innodb_undo_directory,并确保innodb_undo_tablespaces >= 2,然后重启 mysqld。此时新段会落在新路径,旧段仍在原处 - 第二步:让业务流量逐步收敛,监控
SHOW ENGINE INNODB STATUS\G中的History list length降到接近 0,再手动执行DROP UNDO TABLESPACE innodb_undo_001(仅限 8.0.14+,且该表空间必须为空闲状态)
最易被忽略的一点:即使所有 undo 表空间都删完了,innodb_undo_directory 配置仍必须保留——因为新段分配、purge 截断、崩溃恢复等所有路径解析都依赖它,不是“用了就扔”的临时开关。











