myisam 不支持事务,所有写操作立即持久化且不可回滚;其无mvcc、undo log和redo log,无法实现原子性、一致性与崩溃恢复,迁移至innodb需注意全文索引、主键约束及锁表现差异。

MyISAM 不支持事务,这是硬性限制
MyISAM 存储引擎从设计上就完全不提供事务能力,START TRANSACTION、COMMIT、ROLLBACK 这些语句在 MyISAM 表上执行不会报错,但实际没有任何效果——所有写操作都是立即持久化、不可回滚的。这不是配置问题,也不是版本差异,而是引擎内核层面的缺失。
对比 InnoDB:事务支持不是“开关”,而是底层机制差异
MyISAM 用表级锁 + 简单的 B-Tree 索引结构实现快速读取;InnoDB 则依赖 MVCC(多版本并发控制)、undo log 和 redo log 构建事务基础。这意味着:
-
SELECT ... FOR UPDATE在 MyISAM 下被忽略,InnoDB 才真正加行锁 - 崩溃后,MyISAM 可能丢失部分写入且需手动
REPAIR TABLE;InnoDB 能通过 redo/undo 自动恢复到一致状态 - 即使你把 MyISAM 表包在
BEGIN/COMMIT里,也起不到原子性保障作用
什么时候还可能遇到 MyISAM?迁移前务必检查
MySQL 5.7 默认引擎已是 InnoDB,但以下场景仍可能残留 MyISAM:
- 老系统直接升级未做引擎转换(尤其 WordPress、Discuz! 等旧 CMS 的系统表)
-
CREATE TABLE语句显式指定ENGINE=MyISAM - 使用
mysqldump --no-create-info恢复时漏掉引擎声明,依赖默认值(低版本默认是 MyISAM)
查当前库中所有 MyISAM 表:
SELECT table_schema, table_name, engine FROM information_schema.tables WHERE engine = 'MyISAM';
迁移到 InnoDB 不只是改 ENGINE,还要注意隐含约束
执行 ALTER TABLE t1 ENGINE=InnoDB 看似简单,但容易踩坑:
- 全文索引在 MyISAM 中支持布尔模式,在 InnoDB 中直到 MySQL 5.6 才支持,且语法细节不同(如
IN NATURAL LANGUAGE MODE行为有差异) - MyISAM 允许
NULL值的主键字段,InnoDB 不允许(主键列必须NOT NULL) - 大表转换会锁表较久,生产环境建议用
pt-online-schema-change或 MySQL 8.0+ 的原地 DDL
事务不是可选功能,而是数据一致性的底线。只要业务需要“要么全成功、要么全失败”,MyISAM 就不该出现在你的写入路径里。










