pt-online-schema-change是最稳妥的准在线批量转换工具,它通过创建影子表、触发器同步、分块拷贝和原子替换实现无锁改表,但需满足主从延迟为0、无FULLTEXT索引、innodb_file_per_table=ON、表有主键或唯一非空索引四大前提。

pt-online-schema-change 是目前最稳妥的离线(实为“准在线”)批量转换工具,它不依赖 MySQL 版本内置 DDL 能力,也不要求停机——但前提是你的环境能跑通它。直接执行 ALTER TABLE ... ENGINE=InnoDB 在升级前批量操作,等于主动触发锁表、磁盘暴涨、主从延迟崩盘,这不是准备升级,是在制造故障窗口。
为什么不能用 mysqldump + 导入方式“离线”转换
看起来是彻底离线、可控、可验证,实际落地时容易翻车:
– 大表导出时 mysqldump --single-transaction 对 MyISAM 无效(它不支持事务),只能加 --lock-all-tables,整库只读;
– 导入时若忘记指定 ENGINE=InnoDB,新表还是 MyISAM;
– AUTO_INCREMENT 列没索引、FULLTEXT 分词差异、大小写敏感等兼容性问题,在导入后才暴露,回滚成本高;
– 无法增量同步转换期间的写入,业务必须完全停写,窗口不可控。
pt-online-schema-change 执行前必须检查的四件事
pt-online-schema-change 不是黑盒,它靠触发器双写维持一致性,环境稍有偏差就会失败或数据错乱:
- 确认主从复制正常且
Seconds_Behind_Master = 0,否则影子表数据会滞后 - 确保目标表没有
FULLTEXT索引(MyISAM 的 FULLTEXT 无法被 pt-osc 自动迁移,需先DROP INDEX) - 检查
innodb_file_per_table = ON,否则所有新表数据挤进ibdata1,后续无法清理 - 表必须有主键或唯一非空索引(
pt-osc依赖它分块拷贝,否则报错Cannot chunk the table)
生成并执行批量转换命令的最小可行脚本
别手敲、别拼接 SQL 字符串后 source,用 shell + pt-online-schema-change 控制并发和失败重试:
mysql -Nse "SELECT CONCAT('pt-online-schema-change --alter \"ENGINE=InnoDB\" --execute h=localhost,u=root,p=xxx,D=your_db,t=', table_name, ' 2>&1 &') FROM information_schema.tables WHERE table_schema='your_db' AND engine='MyISAM'" | sh
更安全的做法是先生成命令列表,人工 review 后分批执行:
mysql -Nse "SELECT CONCAT('pt-online-schema-change --alter \"ENGINE=InnoDB\" --execute --critical-load=\"Threads_running=25\" --max-lag=1s h=localhost,u=root,p=xxx,D=your_db,t=', table_name) FROM information_schema.tables WHERE table_schema='your_db' AND engine='MyISAM' ORDER BY data_length DESC" > convert.sh
执行时加 --critical-load 和 --max-lag 防止拖垮主从;大表优先,避免小表跑完后大表又卡住资源。
MySQL 8.0.34+ 用户注意:ALGORITHM=INSTANT 仍不支持引擎切换
哪怕你用的是最新版 MySQL,ALTER TABLE t ENGINE=InnoDB ALGORITHM=INSTANT 依然会报错 ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation。引擎切换在所有已发布版本中都强制走 COPY 模式,ALGORITHM=INPLACE 仅适用于加字段、改列类型等有限场景。别被文档里“支持 INPLACE”的描述误导——查清楚具体操作类型再下手。
真正容易被忽略的是转换后行为变化:InnoDB 的 COUNT(*) 变慢、默认隔离级别变成 REPEATABLE-READ、外键约束开始生效、SELECT ... FOR UPDATE 锁行而非锁表……这些不是“转换完成”的标志,而是新问题的起点。











