不建议在只读从库上将引擎改为MyISAM——会引发复制断裂、数据不可信、元数据锁死、性能反降等风险,且MySQL 8.0.33+已默认禁用该引擎。

不建议在只读从库上将引擎全部改为MyISAM——这不是性能优化,而是引入单点故障和复制断裂风险。
为什么SHOW SLAVE STATUS看起来正常,但数据已不可信
主库用InnoDB + binlog_format=ROW是当前生产环境绝对主流;从库强行改MyISAM后,复制线程仍能持续运行,Seconds_Behind_Master可能长期显示为 0,但这是假象。因为ROW格式的binlog事件(如UPDATE @1=100,@2='new')无法被MyISAM表正确应用:它没有事务回滚能力、不支持行级变更语义,遇到缺失行或类型不匹配时会静默跳过,不报错也不记录。你查不到错误,但SELECT COUNT(*)和主库对不上,且这种偏差不可逆。
- 实测中,持续运行 48 小时后,某销售汇总表行数偏差达 0.7%,而
SHOW SLAVE STATUS始终无异常 -
REPAIR TABLE会重写.MYD/.MYI,彻底破坏与主库的二进制一致性,后续即使切回InnoDB也无法靠binlog追平 - ProxySQL等中间件检测到
MyISAM表无事务上下文,可能把本该路由到从库的查询打到主库,反而加重主库压力
MyISAM在高并发只读下的真实瓶颈不是CPU或IO
很多人压测时只看QPS和平均响应时间,却忽略MyISAM在高并发下对.MYI文件头的争抢。每个SELECT都要读取索引文件头里的行计数、键分布统计等元数据,这些小读操作在文件系统层形成热点,导致大量read()系统调用排队。这和InnoDB的innodb_buffer_pool_size缓存热页、避免磁盘访问的机制完全不同。
- 并发线程 >200 时,
iostat -x 1可见%util不高但r_await飙升至 20ms+,说明是随机小IO等待,不是带宽瓶颈 -
key_buffer_size再大也无济于事——它只缓存索引块,不缓存文件头元数据 - 用
perf record -e syscalls:sys_enter_read -p $(pgrep mysqld)可直接观察到该现象
ALTER TABLE ENGINE=MyISAM在从库上极易卡死
执行ALTER TABLE t ENGINE=MyISAM时,MySQL需获取MDL_EXCLUSIVE锁。但在从库上,复制SQL线程本身也在持有该表的MDL_SHARED_READ锁(用于读取relay log并应用)。二者冲突,导致DDL无限等待。此时SHOW PROCESSLIST里看不到明显阻塞线程,只显示Waiting for table metadata lock,而复制线程状态仍是Reading event from the relay log,非常隐蔽。
- 检查方法:
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA='db' AND OBJECT_NAME='t';,会看到两行锁记录,type均为TABLE,但LOCK_TYPE分别为EXCLUSIVE和SHARED_READ - 唯一解法是临时停掉复制:
STOP SLAVE SQL_THREAD;,但停期间延迟累积,恢复后可能触发大量慢日志刷盘 - 若表上有
FULLTEXT索引,MySQL 8.0+ 会直接拒绝转换,报错ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes
真正影响只读从库性能的从来不是引擎,而是索引和缓冲配置
把精力花在MyISAM上,等于在修自行车轮子的同时无视爆胎的轮胎。同样一张用户状态表,InnoDB配innodb_buffer_pool_size=60% RAM + 覆盖索引,QPS稳定在 12000;而MyISAM即使调大key_buffer_size,只要查询涉及SELECT name,email,phone FROM user WHERE status=1这类多字段返回,就必须反复读.MYD,QPS很快跌到 4000 以下。
-
SELECT COUNT(*)慢?不是InnoDB问题,是没设innodb_stats_method=keep_initialized,导致每次执行都重新采样 - 范围扫描慢?大概率缺联合索引,而不是引擎选错;
EXPLAIN FORMAT=TREE比换引擎更能定位问题 - 从库延迟高?先查
Replica_SQL_Running_State是否卡在Updating main tables,这往往意味着大事务或没走索引的UPDATE,和引擎无关
最常被忽略的一点:MySQL 8.0.33+ 默认禁用MyISAM引擎,配置项disabled_storage_engines=MyISAM已成标配。你连CREATE TABLE ... ENGINE=MyISAM都会直接报错Unknown storage engine 'MyISAM',更别说在线修改了。



















