MySQL 8.0默认ROW格式binlog下,MyISAM从库无法可靠回放:SQL线程遇行事件即报错或静默跳过,ALTER TABLE ENGINE=MyISAM致复制中断;read_only对MyISAM无效,AUTO_INCREMENT不持久,表级锁拖垮并发,崩溃后无日志恢复,数据错位风险高。

MyISAM在从库上根本无法可靠回放ROW格式binlog
MySQL 8.0默认binlog_format=ROW,而MyISAM不支持行级事件解析。从库IO线程能正常拉取relay log,但SQL线程一遇到INSERT INTO t VALUES (1,'a')这类ROW事件就卡住,报错ERROR 1594 (HY000): Relay log read failure或静默跳过——后者更危险,数据错位但无提示。
常见误操作是手动在从库执行ALTER TABLE t ENGINE=MyISAM,结果主库后续任何DDL(哪怕只是ADD COLUMN)都会让复制中断,且START SLAVE无法恢复。
- MyISAM表在ROW模式下无法被SQL线程识别为合法目标,复制退化为不可靠的STATEMENT模式
- 非确定性函数如
NOW()、UUID()在主从产生不同值,报表类业务直接失效 - 即使主库也用MyISAM,只要启用
gtid_mode=ON,从库启动时就会拒绝加载MyISAM系统表
read_only=ON对MyISAM形同虚设
设置read_only=ON本意是防止从库误写,但MyISAM对INSERT DELAYED、LOAD DATA INFILE、REPAIR TABLE等操作完全不检查该参数。这些操作一旦执行,立刻破坏主从一致性,且不会触发任何告警。
更隐蔽的问题是:MyISAM的AUTO_INCREMENT值不持久,MySQL重启后需全表扫描找最大ID,导致从库重启后首次插入ID跳变,关联查询结果断裂。
-
INSERT DELAYED在MyISAM中仍可写入,且不走binlog,主库完全不知情 -
REPAIR TABLE会重建.MYI索引文件,但原.MYD数据可能已损坏,修复后逻辑不一致 - 权限控制无法覆盖MyISAM特有操作,
SUPER权限用户绕过read_only毫无难度
并发查询反而被MyISAM表级锁拖垮
读写分离本意是分流高并发查询,但MyISAM的表级锁机制会让多个SELECT竞争同一把锁。尤其当有ANALYZE TABLE、OPTIMIZE TABLE或后台统计任务运行时,整张表查询全部阻塞,QPS断崖下跌。
实测显示:10万行订单历史表在TPS 300+时,MyISAM从库CPU常飙至95%,InnoDB稳定在60%以下。原因在于InnoDB的行锁+MVCC让读写互不阻塞,而MyISAM一个慢查询就能锁死整张表。
-
SELECT COUNT(*)在MyISAM中虽快,但会持有读锁,阻塞所有其他SELECT - 覆盖索引查询在InnoDB中可完全避免回表,MyISAM索引与数据分离,频繁随机IO加剧延迟
- 中间件如ProxySQL检测到MyISAM表无事务上下文,可能误判为“强一致性需求”,把查询路由回主库
崩溃恢复后MyISAM状态不可信
InnoDB崩溃后靠redo log自动前滚恢复,整个过程无需人工干预;MyISAM没有日志机制,断电或异常退出后.MYD和.MYI文件极易错位,CHECK TABLE常报error: 134 (record header crashed),此时REPAIR TABLE只是暴力重写索引,无法验证数据逻辑正确性。
真正麻烦的是:这种损坏往往不立即暴露。可能连续数周查询都“看起来正常”,直到某次财务对账才发现金额字段丢失或重复——因为MyISAM根本不校验行完整性。
- MyISAM无UNDO LOG,无法回滚部分写入,也无法检测半截记录
- 备份工具
mysqldump --single-transaction对MyISAM表退化为全局FLUSH TABLES WITH READ LOCK,阻塞所有写入 - MySQL 8.0.33+已弱化
REPAIR TABLE功能,对崩溃MyISAM表修复成功率极低
innodb_buffer_pool_size、ROW_FORMAT=COMPRESSED)已抹平其原始优势,而它遗留的风险点——复制中断、静默错乱、修复失败——却在分布式场景中被急剧放大。


















