必须将主库myisam表转为innodb,因myisam不支持row格式复制且易致sql线程中断;alter需在低峰期执行,避免跳过错误或仅改从库引擎,否则引发数据不一致或崩溃。

MyISAM表导致SQL线程中断的典型表现
主从复制中出现 Slave_SQL_Running: No,Seconds_Behind_Master 变为 NULL,且 Last_SQL_Error 显示类似 Table is read only 或 Got error 1296 from storage engine —— 这不是偶发故障,而是 MyISAM 在 ROW 或 MIXED 复制模式下根本无法安全重放 binlog 事件的必然结果。
MyISAM 不支持事务、不支持行级锁、没有崩溃恢复机制,而 MySQL 主从复制(尤其在 binlog_format=ROW 下)依赖存储引擎能精确还原每行变更。从库执行 UPDATE/DELETE 时,MyISAM 可能因锁表失败或状态不一致直接报错退出 SQL 线程。
为什么不能只改从库引擎而不动主库
主从引擎不一致会破坏复制语义:主库用 MyISAM 执行语句,从库用 InnoDB 重放,看似“跑通”,实则埋雷。例如:
- MyISAM 的 AUTO_INCREMENT 行为与 InnoDB 不同,可能导致主从 ID 偏移
- MyISAM 对
INSERT ... SELECT或REPLACE INTO的处理逻辑差异,引发数据覆盖或丢失 - 主库 MyISAM 表被
OPTIMIZE TABLE重建后,从库 InnoDB 表结构未同步,后续 DML 可能列顺序错位
更关键的是:MySQL 5.7+ 在检测到主库表为 MyISAM 且 binlog_format=ROW 时,会直接拒绝启动 SQL 线程,并报错 Cannot execute statement: binlogging impossible since the storage engine of table ... does not support it。
ALTER TABLE ENGINE=InnoDB 必须在主库执行
必须在主库上执行 ALTER TABLE t ENGINE=InnoDB,而不是跳过错误或仅在从库改。原因很直接:
- 主库写入的 binlog 记录的是原始表结构和引擎信息;如果只改从库,binlog 里仍按 MyISAM 解析事件,SQL 线程执行时会因引擎不匹配失败
- mysqldump 导出再导入会丢掉自增值、触发器、binlog position,极易导致主从 GTID 或位置点错乱
-
ALGORITHM=COPY是唯一可行方式(MyISAM → InnoDB 不支持INPLACE),意味着主库该表会全程锁写,且从库需同步执行相同耗时操作 —— 必须选低峰期,提前查表大小:SELECT table_name, round(((data_length + index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.tables WHERE table_schema = 'db_name' AND table_name = 't';
大表转换的实操避坑点
单表超 50GB 时,别硬扛:
- 先停掉从库 SQL 线程:
STOP SLAVE SQL_THREAD;,再在从库单独执行ALTER TABLE t ENGINE=InnoDB,验证无报错、数据行数一致 - 确认从库转换成功后,再在主库执行同样
ALTER,避免主库长时间不可写影响业务 - 切忌用
SET GLOBAL sql_slave_skip_counter=1跳过错误——MyISAM 相关错误从来不是单条语句问题,而是状态已失衡的信号
引擎一致性不是“建议”,是 ROW/MIXED 复制模式下 MySQL 能稳定运行的底层前提。一旦发现 MyISAM 表,优先级应高于索引优化或慢查询调优。











