MyISAM 表在 MySQL 主从复制中不可靠,因不支持事务导致 binlog 与表更新非原子,易丢数据;InnoDB 凭借 crash-safe 和 XID 关联机制保障复制一致性,是唯一稳妥选择。

MyISAM 表在 MySQL 主从复制中会丢数据
主从切换或从库重启后,MyISAM 表的自增 ID、计数器(如 AUTO_INCREMENT)、甚至部分 INSERT ... SELECT 操作结果可能不一致。这是因为 MyISAM 不支持事务,binlog 写入和表文件更新不是原子的;主库写完 binlog 后崩溃,从库重放时可能已跳过某些行,或者从库用的是非一致性快照恢复。
- 所有 MyISAM 表在主从环境都应视为「不可靠复制目标」,哪怕当前没出问题
-
SHOW SLAVE STATUS看不到错误,但Seconds_Behind_Master可能长期为 0,掩盖了数据逻辑错位 - 如果必须保留 MyISAM(比如旧插件依赖),需确保该表完全不参与写操作——只读 +
read_only=ON在从库上硬限制
InnoDB 是主从复制唯一稳妥的选择
InnoDB 的 crash-safe 特性让 binlog 和引擎层日志(redo log)能通过 XID 关联,在主库崩溃恢复时保证「要么全提交,要么全回滚」;从库重放 binlog 时也能严格按事务边界执行,避免半写状态传播。
- 确认主从都启用
innodb_support_xa=ON(MySQL 5.7+ 默认开启,但低版本需检查) - 主库
binlog_format必须为ROW:STATEMENT模式下NOW()、UUID()等函数在从库重放会出错 - 避免在从库执行
INSERT INTO t SELECT ...类语句——InnoDB 虽安全,但这类操作会阻塞 SQL 线程,且无法并行回放
读写分离中间件对 MyISAM 和 InnoDB 的路由差异
ShardingSphere、MaxScale、ProxySQL 这类工具默认按语法解析判断读写,但 MyISAM 表的 SELECT COUNT(*) FROM t 可能被误判为「需要强一致性」而打到主库;InnoDB 表则更易被识别为可路由到从库(尤其带 WHERE 条件时)。
- MyISAM 的
SELECT即使加了FOR UPDATE也不起作用,中间件可能因检测不到锁机制而降级路由策略 - InnoDB 的
SELECT ... LOCK IN SHARE MODE或显式事务会被中间件识别为「写倾向」,自动避开从库 - 若用
/*+ READ_FROM_SLAVE */这类 hint,MyISAM 表仍可能返回陈旧值——因为它的key_buffer缓存不参与 binlog 事件同步
从 MyISAM 迁移到 InnoDB 的实际卡点
直接 ALTER TABLE t ENGINE=InnoDB 在大表上会锁表、耗内存,且可能触发从库延迟飙升;更麻烦的是外键、全文索引、PACK_KEYS 等 MyISAM 特有特性在 InnoDB 中行为不同。
- 全文索引需改用
MATCH ... AGAINST语法,且分词器配置(ft_min_word_len)在 InnoDB 中不可动态改 - 外键约束在从库上默认关闭(
foreign_key_checks=OFF),迁移后需手动校验一致性 - 用
pt-online-schema-change执行在线转换时,注意它依赖REPLACE INTO,而 MyISAM 对重复键处理是覆盖,InnoDB 是报错——需提前清理冲突数据
真正麻烦的从来不是命令敲得对不对,而是 MyISAM 表里那些没写进文档的隐式依赖:某个 cron 脚本直接读取 /var/lib/mysql/db/t.MYD 文件,或者监控脚本用 myisamchk 检查表状态——这些在 InnoDB 迁移后全得重写。











