必须将主库myisam表转为innodb,因myisam不支持row格式复制且无事务、无行级锁、无崩溃恢复能力,强行使用会导致sql线程报错、数据静默不一致或从库误写失控。

MyISAM表在ROW格式复制下直接报错
MySQL 5.7+ 默认 binlog_format 是 ROW,而 MyISAM 存储引擎**不支持 ROW 格式下的事件重放**。一旦主库产生基于行的 binlog(比如 UPDATE 某行、DELETE 某行),从库 SQL 线程尝试回放时会立即失败,报错类似:Cannot execute statement: binlogging impossible since the storage engine of table ... does not support it。这不是配置没调好,是引擎层硬性限制——MyISAM 没有事务、没有行级锁、没有崩溃恢复能力,根本无法安全还原 ROW 事件的语义。
STATEMENT格式下看似能跑,实则埋雷
如果手动把 binlog_format 改成 STATEMENT,MyISAM 表可能暂时同步成功,但极易在以下场景翻车:
-
NOW()、UUID()、USER()等非确定性函数:主库执行结果和从库执行结果不同,导致数据分叉 - 带 LIMIT 的 UPDATE/DELETE:主库影响 1 行,从库因排序差异可能影响 0 行或 2 行
- 自增字段插入:MyISAM 的
AUTO_INCREMENT不保证主从一致,尤其并发写入时
这类问题不会立刻报错,而是静默造成逻辑不一致,等业务对账才发现钱对不上。
从库写入 + MyISAM = 高危组合
MyISAM 表默认可写,且没有事务保护。如果误操作在从库执行了 UPDATE 或 INSERT,或者应用层直连从库做了写操作,数据立刻偏离主库。更麻烦的是:MyISAM 不记录 undo log,也没 crash recovery 机制,一旦从库宕机重启,可能连“自己改过什么”都记不清,根本没法回滚或比对。
而 InnoDB 表配合 read_only=ON(从库强制只读)能天然拦截这类误写,MyISAM 则完全不设防。
ALTER TABLE ENGINE=MyISAM → InnoDB 的坑
主库上执行 ALTER TABLE t ENGINE=InnoDB 时,MySQL 必须走 COPY 模式(MyISAM 转 InnoDB 不支持 ALGORITHM=INPLACE),整个过程锁表、阻塞 DML,且 binlog 记录的是“建新表 + 导入全量数据”,从库需同步执行同等耗时操作。若中途失败或超时,极易卡在中间状态,导致主从结构不一致。
真正安全的做法是:先停掉从库 SQL 线程,在从库单独完成转换并验证数据,再在主库低峰期执行,最后恢复复制。跳过这步直接在主库硬转,等于把风险集中到最脆弱的一环。
MyISAM 引擎本身不是 bug,但它和现代复制机制(ROW 格式、GTID、并行复制)存在底层设计冲突。只要主从里还混着 MyISAM 表,数据一致性就永远悬着一把刀——不是“会不会出问题”,而是“什么时候出”。











