myisam 在 mysql 高可用集群中不可用,因其无事务、崩溃后不保证一致性,易导致切换后索引损坏、数据丢失或“table is marked as crashed”;必须全部转为 innodb 并规范配置与操作。

MyISAM 在 MySQL 高可用集群里根本不能用
MySQL 高可用架构(比如 MHA、Orchestrator、InnoDB Cluster、甚至主从 + VIP)默认假设所有节点数据状态一致、能安全切换主库。而 MyISAM 表没有事务、崩溃后不保证行级一致性,主库挂了切到从库时,MyISAM 表大概率出现索引损坏、数据丢失或 Table is marked as crashed 错误。
常见错误现象:
- 主库异常宕机后,从库提升为主库,应用一写入就报
Got error 127 from storage engine -
SHOW TABLE STATUS显示Comment字段为Crashed - MHA 切换成功,但业务连不上——其实是某个
MyISAM系统表(如mysql.columns_priv)坏了
实操建议:
- 上线前必须执行
SELECT ENGINE, COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') GROUP BY ENGINE,确认结果里没有MyISAM - 历史遗留的
MyISAM表,用ALTER TABLE tbl_name ENGINE=InnoDB转换;注意加锁时间长,避开高峰 - 禁止在配置文件中设置
default-storage-engine=MyISAM,必须显式写成default-storage-engine=InnoDB
InnoDB 的复制兼容性取决于事务隔离与 DDL 模式
InnoDB 是高可用集群的唯一可行引擎,但不是“只要用了就自动兼容”。问题出在:不同 MySQL 版本对 CREATE TABLE 默认行为、隐式事务、DDL 锁策略的处理差异,会导致主从复制中断或数据不一致。
使用场景:
- MySQL 5.7 升级到 8.0 后,
sql_mode默认增加STRICT_TRANS_TABLES,原来能插入的脏数据在从库报错中断复制 - 用
ALGORITHM=INPLACE加字段时,MySQL 5.6 不支持,会退化为拷表,在大表上阻塞主库写入,导致从库延迟飙升 - 开启
binlog_format=STATEMENT时,NOW()、UUID()这类函数在主从产生不同值,违反一致性
实操建议:
- 全集群统一
binlog_format=ROW,且开启binlog_row_image=FULL(避免部分更新导致从库补全失败) - 所有 DDL 操作前先查目标版本文档,例如 MySQL 8.0.12+ 才支持
INSTANT算法添加列,旧版本别信 ORM 自动生成语句 - 应用层避免依赖
SELECT ... FOR UPDATE跨事务长时间持有锁;高可用切换时持有锁的事务可能被强制 kill,引发死锁重试风暴
集群脑裂时 InnoDB 的 auto-increment 行为会放大冲突
当网络分区导致双主(例如 MHA 未及时下线旧主、或 Group Replication 配置不当),两个节点同时向同一张 InnoDB 表插入数据,auto_increment 值会重复。即使后来网络恢复,GTID 或 position 复制也无法自动修复主键冲突。
常见错误现象:
- 从库报错
Duplicate entry '12345' for key 'PRIMARY',且无法跳过(因为是 GTID 模式) - 手动
SET GLOBAL auto_increment_increment后忘记同步到所有节点,下次分区又撞上
实操建议:
- 强制所有写节点配置
auto_increment_increment=2和auto_increment_offset=1(主) /auto_increment_offset=2(备),这是最简单有效的规避手段 - 禁用
innodb_autoinc_lock_mode=0(传统锁模式),改用2(交错模式),减少 INSERT ... SELECT 场景下的锁争用 - 业务层关键表主键尽量不用
AUTO_INCREMENT,改用雪花算法或数据库序列服务生成 ID
备份恢复链路里 MyISAM 是静默断点
物理备份(xtrabackup)能备份 MyISAM 文件,但恢复后不会校验其索引完整性;逻辑备份(mysqldump)默认不带 --force,遇到 MyISAM 表损坏直接退出,而你可能只看到 “dump finished”,没注意到某张表根本没导出成功。
实操建议:
- xtrabackup 备份后,必须在测试环境执行
mysqlcheck --all-databases --check,重点看MyISAM表返回是否含status: OK - mysqldump 加
--force --skip-lock-tables,并解析输出日志中是否出现Warning: Skipping the data of table xxx because it cannot be processed - 任何自动化备份脚本,都要在最后加一句
grep -q "MyISAM" /var/lib/mysql/mysql/proc.MYD && echo "CRITICAL: MyISAM found" >&2
真正麻烦的不是转换引擎,而是那些藏在 mysql 系统库里的 MyISAM 表——比如老版本的 mysql.procs_priv,没人动它,但它会在集群重建时突然让你的权限系统失效。











