不能用alter table engine=innodb实现不停服迁移——它在任何mysql版本中对myisam表均强制走copy算法,全程持mdl写锁阻塞写入,磁盘需双倍空间;唯一可靠方案是pt-online-schema-change,依赖主键或唯一索引、innodb_file_per_table=on、row格式binlog及零主从延迟,迁移后须人工校验并清理旧文件。

不能用 ALTER TABLE ENGINE=InnoDB 实现不停服迁移——它在任何 MySQL 版本(包括 8.0)中对 MyISAM 表都强制走 COPY 算法,全程持有 MDL 写锁,业务写入必然中断。
为什么 ALTER TABLE ENGINE=InnoDB 必然停服
这不是语法问题,是 MySQL 底层机制决定的硬限制:MyISAM → InnoDB 的引擎切换不支持 ALGORITHM=INPLACE,只能全量拷贝。过程表现为:
-
SHOW PROCESSLIST中状态长期卡在copy to tmp table,不是“准备中”,是真的在搬数据 - 持有全局
MDL写锁,所有INSERT/UPDATE/DELETE被阻塞;SELECT在REPEATABLE READ隔离级别下也可能被卡住 - 磁盘空间需 ≥ 原
.MYD+.MYI总大小 × 2(含 redo/undo/临时文件),10GB 表就得预留 20GB+ 空间 - 即使显式加
LOCK=NONE,MySQL 也会自动降级为LOCK=EXCLUSIVE
真正能不停服的方案只有 pt-online-schema-change
它通过影子表 + 触发器双写同步变更,原表持续可读写,业务无感。但必须满足前提条件:
- 目标表必须有主键或唯一非空索引(否则报错
This table has no primary key or unique index) -
innodb_file_per_table = ON(MySQL 5.6+ 默认开启,但需确认) -
binlog_format = ROW(pt-osc依赖行级日志同步) - 禁用
LOAD DATA INFILE、REPLACE INTO等绕过触发器的操作
典型命令:
pt-online-schema-change --alter "ENGINE=InnoDB" D=your_db,t=big_table --execute
关键参数建议:
--chunk-size=500(降低单次压力)、--max-lag=5(从库延迟超 5 秒自动暂停)。
迁移后必须人工清理和验证
pt-osc 完成后不会自动删除旧的 .MYD/.MYI 文件,这是最容易被忽略的风险点:
- 先比对新旧表行数:
SELECT COUNT(*) FROM old_tablevsSELECT COUNT(*) FROM new_table(同事务隔离级别下执行) - 再抽样校验数据一致性,避免因 NULL 处理、字符集排序规则(如
utf8mb4_0900_as_csvsutf8mb4_general_ci)导致哈希不一致 - 确认无误后,手动
rm /var/lib/mysql/your_db/old_table.{MYD,MYI} - 注意:迁移后
FULLTEXT索引需重建(ALTER TABLE t DROP INDEX ft_idx; ALTER TABLE t ADD FULLTEXT(...)),分词逻辑与 MyISAM 不同
真正难的不是执行命令,而是判断哪张表该迁、哪张不该动,以及迁移后那些隐性行为变化——比如 SELECT COUNT(*) 变慢、AUTO_INCREMENT 字段必须参与索引、INSERT DELAYED 彻底失效。这些细节不提前对齐,停服时间反而更长。











