应先筛选再迁移MyISAM表——仅对有持续写入、数据量超1GB(SSD≥500MB)、需事务/行锁/崩溃恢复的表执行转换;只读小表及含FULLTEXT索引的表可暂缓。

不能直接批量执行 ALTER TABLE t ENGINE=InnoDB —— 会锁死写入、吃光磁盘、拖垮主从,且 MySQL 8.0+ 仍强制走 COPY 算法,所谓“在线”是假象。
哪些 MyISAM 表真该转?先筛再动
盲目转换可能引入全文索引不兼容、AUTO_INCREMENT 报错 ERROR 1075、甚至性能反降。先跑这句查出待评估清单:
SELECT table_schema, table_name, table_rows, data_length FROM information_schema.tables WHERE engine = 'MyISAM' AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema');
重点关注三类表:
- 有持续写入(
table_rows非静态) - 数据量 >1GB(SSD 上 ≥500MB 就建议走无锁方案)
- 业务依赖事务、行锁或崩溃恢复能力
可暂缓迁移的表:
- 只读小表(≤100MB,比如配置表、字典表)
- 含
FULLTEXT索引但 MySQL 版本 - 无主键/唯一非空索引(
pt-online-schema-change会报错This table has no primary key or unique index)
大表必须用 pt-online-schema-change,别信 ALGORITHM=INPLACE
MySQL 5.7/8.0 对 ENGINE 变更仍强制走 COPY 算法,ALGORITHM=INPLACE 不生效。唯一能绕开锁表的成熟方案是 pt-online-schema-change,原理是影子表 + 触发器双写。
前提硬性要求:
- 目标表必须有主键或唯一非空索引(否则无法分片同步)
-
innodb_file_per_table=ON(MySQL 5.6+ 默认开启,确认下) - 禁用
LOAD DATA INFILE或REPLACE INTO等绕过触发器的操作
命令示例(带关键参数):
pt-online-schema-change --alter "ENGINE=InnoDB" D=your_db,t=big_table --execute --chunk-size=1000 --max-lag=1 --check-interval=5
注意:pt-osc 迁移后不会自动删除旧的 .MYD 和 .MYI 文件,必须人工清理——先验证新表数据一致,再删。
转换后不调参等于白转,InnoDB 行为和 MyISAM 差太多
引擎改完立刻验证两件事:
-
COUNT(*)结果是否与原表一致(InnoDB 不缓存行数,结果可能慢但准确) - 业务 SQL 是否仍能正常执行,尤其涉及
MATCH AGAINST的全文查询(InnoDB 分词规则不同,需重建索引)
必须调整配置项:
-
innodb_buffer_pool_size设为物理内存的 50%–75% -
key_buffer_size从几百 MB 降到 32M 左右(MyISAM 不再用) -
innodb_flush_log_at_trx_commit非金融场景可设为 2(崩溃最多丢 1 秒数据)
特别注意:若原表含 AUTO_INCREMENT 但没建索引,ALTER TABLE 会直接报错;而 pt-osc 虽能绕过锁,但迁移后仍要补主键约束,否则后续加索引或外键会失败。


















