MyISAM表在事务中无法回滚,因其不支持事务,所有操作立即生效且不可逆;混用InnoDB与MyISAM会导致数据不一致、备份错乱、主从复制中断及高可用切换失败等严重问题。

事务回滚时MyISAM部分无法撤销
在一个 BEGIN…COMMIT 事务中同时操作 InnoDB 表和 MyISAM 表,InnoDB 部分能回滚,MyISAM 部分一旦写入就立即生效、不可逆。
常见误用场景:下单逻辑里用事务包裹「扣库存(InnoDB)+ 记日志(MyISAM)」,结果库存回滚了,日志却已落盘——后续对账发现订单不存在但日志有记录。
- MySQL 不会报错,也不会警告,行为完全静默
-
ROLLBACK只影响InnoDB表,MyISAM表的变更不会被清理 - 哪怕只执行一条
INSERT INTO myisam_table,它也立刻持久化
备份一致性彻底失控
mysqldump 的 --single-transaction 对 MyISAM 表完全无效,混用时若不加全局锁,备份出来的 InnoDB 和 MyISAM 数据时间点不一致。
典型错误现象:备份文件里订单表(InnoDB)是凌晨 2:00 的状态,而关联的日志表(MyISAM)却是 2:15 的内容,恢复后查不到对应日志或出现重复记录。
- 必须二选一:
--lock-all-tables(全局只读锁,停写 ≤30 秒)或统一转成InnoDB后再用--single-transaction - 严禁同时指定
--single-transaction和--lock-tables,后者会被静默忽略 -
mydumper --less-locking可缓解,但仅限 MyISAM 表极少且版本 ≥0.10.0 的场景
主从复制极易中断或静默错乱
主库用 InnoDB、从库存在 MyISAM 表时,ROW 格式 binlog 无法正确应用到 MyISAM 表,复制线程会卡在 ERROR 1032 或 ERROR 1594。
更危险的是“静默错乱”:某些 UPDATE 因字段顺序或默认值差异,在 MyISAM 表上执行失败但未报错,数据实际已偏移,SHOW SLAVE STATUS 显示正常,直到某次对账才发现差异。
-
read_only=ON对MyISAM无效:INSERT DELAYED和LOAD DATA INFILE仍可写入,破坏只读语义 - 主库执行
ALTER TABLE,从库若为MyISAM会直接中断复制,且无法自动恢复 - MySQL 8.0+ 系统表已全为
InnoDB,继续混用等于主动放弃官方支持路径
高可用切换后大概率数据损坏
集群(如 MHA、InnoDB Cluster)发生主库宕机切换时,MyISAM 表因无崩溃恢复机制,从库提升为主库后常报 Table is marked as crashed 或 Got error 127 from storage engine。
这不是小概率事件——只要主库异常退出前有未刷新的 .MYD 缓冲,或索引页写一半,从库接管后就会触发校验失败。修复需 REPAIR TABLE,而这又是阻塞式操作,等于二次停服。
-
CHECK TABLE在MyISAM上会全表扫描索引文件,期间表不可写,线上执行等于主动卡死 - 即使只是系统库里的
mysql.columns_priv是MyISAM,也可能导致权限校验失败,整个集群无法登录 - 所有历史遗留
MyISAM表必须用ALTER TABLE tbl_name ENGINE=InnoDB转换,且必须避开业务高峰
COUNT(*) 元数据“蒙混过关”的老表——它们不会在迁移时出声,却会在某个凌晨三点的对账任务里突然露馅。


















