MySQL 5.7 中 ALTER TABLE ... ENGINE=InnoDB 对 MyISAM 表强制使用 COPY 算法,全程持有 MDL 写锁,DML 完全阻塞,并不真正在线;唯一可行的批量方案是 pt-online-schema-change,但需满足主键/唯一索引、innodb_file_per_table=ON、提前删除 FULLTEXT 索引等前提,且必须严格校验主从延迟、隐式依赖及 AUTO_INCREMENT 列索引。

不能真正“在线”批量转换——MySQL 5.7 的 ALTER TABLE ... ENGINE=InnoDB 对 MyISAM 表强制走 COPY 算法,全程持有 MDL 写锁,INSERT/UPDATE/DELETE 全部阻塞,所谓“在线”只是最后元数据切换那几十毫秒不锁,业务感知仍是卡顿甚至超时。
为什么 ALTER TABLE ENGINE=InnoDB 在 5.7 中不是在线操作
MyISAM → InnoDB 的引擎变更在 MySQL 5.7 中明确不支持 ALGORITHM=INPLACE,即使显式指定也会被忽略并降级为 COPY。这意味着:
- 原表数据需全量拷贝到新
.ibd文件,期间持续占用双倍磁盘空间 -
SHOW PROCESSLIST会长时间显示copy to tmp table,不是假象,是真的在读写磁盘 - 主库执行时,从库回放该 DDL 也需等锁,
Seconds_Behind_Master可能飙升至数小时 - 若中途失败(如磁盘满、连接断),旧表仍为 MyISAM,但临时文件残留,空间无法自动释放
真正可用的批量方案只有 pt-online-schema-change
它通过影子表 + 触发器双写实现准在线迁移,不锁原表 DML,但有硬性前提和关键参数必须设对:
- 目标表必须有主键或唯一非空索引,否则报错
This table has no primary key or unique index - 确保
innodb_file_per_table = ON(5.7 默认开启,但需确认) - 禁用 FULLTEXT 索引:MyISAM 的
FULLTEXT不会被迁移,必须先ALTER TABLE t DROP INDEX ft_idx - 命令中必须加
--max-lag=1和--check-interval=5,防从库延迟失控 - 大表建议加
--chunk-size=1000(而非默认 1000 行/批),避免单次事务过大
生成批量命令示例:mysql -Nse "SELECT CONCAT('pt-online-schema-change --alter \"ENGINE=InnoDB\" --execute --max-lag=1 --check-interval=5 D=your_db,t=', table_name) FROM information_schema.tables WHERE table_schema='your_db' AND engine='MyISAM'" > convert.sh
执行前必须验证的三件事
跳过任何一项都可能导致迁移中断、数据不一致或应用报错:
- 检查主从延迟:
SHOW SLAVE STATUS\G中Seconds_Behind_Master = 0,且 IO/SQL 线程均为Yes - 确认无隐式 MyISAM 依赖:比如视图底层是 MyISAM 表,或触发器引用了 MyISAM 表,这些不会被脚本自动识别
- 验证
AUTO_INCREMENT列是否已建索引:MyISAM 允许裸id INT AUTO_INCREMENT,InnoDB 要求它必须是主键或联合索引一部分,否则pt-osc同步阶段会报错
最常被忽略的是 FULLTEXT 索引和自增列索引缺失——它们不会在 pt-osc 启动时报错,而是在数据同步快完成时突然失败,此时已耗时几十分钟,重试成本极高。


















