不能直接批量执行 alter table t engine=innodb,因其会锁写入、耗磁盘、拖垮主从,且 mysql 8.0+ 仍强制 copy 算法;应先筛选真正需转换的 myisam 表,避免全文索引不兼容、error 1075 等问题。

不能直接批量执行 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
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文件,必须人工清理——先验证新表数据一致(用CHECKSUM TABLE),再删
小表(≤500MB)可谨慎用 ALTER TABLE
仅限同时满足以下全部条件时才考虑:ALTER TABLE 直接转:
- 无
FULLTEXT索引(否则会直接报错退出) - 已有显式主键或唯一非空索引(避免 InnoDB 静默创建不可控的隐藏
ROW_ID) - 磁盘剩余空间 ≥ 原表
.MYD大小 × 2.2(留出 redo/undo 与碎片余量) - 业务允许该表在转换窗口内完全不可写(例如非核心字典表)
- 执行前务必先在从库验证耗时与锁表现象,别在主库盲试
转换后不调参等于白转
InnoDB 行为和 MyISAM 差太多,引擎改完立刻验证两件事:
-
COUNT(*)结果是否与原表一致(InnoDB 不缓存行数,结果可能慢但准确) - 业务 SQL 是否仍能正常执行,尤其涉及
MATCH AGAINST的全文查询(InnoDB 分词规则不同,需重建索引) - 必须调整配置项:
innodb_buffer_pool_size设为物理内存的 50%–75%,key_buffer_size从几百 MB 降到 32M 左右,innodb_flush_log_at_trx_commit非金融场景可设为 2
最易被忽略的是:pt-online-schema-change 迁移后旧文件不自动清理,且 FULLTEXT 索引需手动重建;调参不到位会导致 InnoDB 缓存命中率低、写放大严重,反而比 MyISAM 更慢。











