InnoDB 支持 ACID 事务、行锁、崩溃自动恢复及持久化 AUTO_INCREMENT,MyISAM 仅支持表锁、无事务、崩溃易丢数据且重启可能重置自增主键,新建项目应优先选 InnoDB。

MyISAM 不支持事务,InnoDB 支持 ACID 事务
如果你的应用需要回滚、提交或崩溃恢复能力,InnoDB 是唯一合理选择。MyISAM 完全忽略事务语义——哪怕你写了 BEGIN 或 ROLLBACK,它也当作普通语句执行,不报错但也不生效。
常见踩坑场景:
- 误以为
INSERT ... SELECT在 MyISAM 中能原子执行,实际中途失败会导致部分写入且无法回退 - 用 MyISAM 做订单表,支付成功后更新状态失败,无法通过事务保证“扣款+改状态”一致性
-
autocommit=0对 MyISAM 表完全无效,COMMIT和ROLLBACK被静默忽略
MyISAM 表锁 vs InnoDB 行锁
MyISAM 对整张表加锁:一个 UPDATE 正在执行,所有其他对这张表的 SELECT、INSERT 都得排队等它完成。InnoDB 默认按索引行加锁(主键或唯一索引),并发能力高得多。
但注意几个关键细节:
- InnoDB 的“行锁”不是万能的:没走索引的
WHERE条件会升级为表锁(例如UPDATE t SET x=1 WHERE y='abc',而y没索引) - MyISAM 的
CONCURRENT INSERT只在表尾追加时有效,且不能有空洞(被DELETE过的行位置不复用) - 高并发写场景下,MyISAM 的锁争用会直接拖垮 QPS,而 InnoDB 即使锁冲突也会尝试等待而非立即失败
崩溃恢复能力差异极大
MyISAM 崩溃后靠 myisamchk 修复,但可能丢数据(尤其写到一半断电),且修复过程需锁表。InnoDB 依赖重做日志(ib_logfile)和双写缓冲(doublewrite),能保证已提交事务不丢失,启动时自动前滚恢复。
典型问题表现:
- MyISAM 表突然变
crashed,SELECT报错Table 'xxx' is marked as crashed and should be repaired - 服务器异常关机后,MyISAM 数据文件(
.MYD)和索引文件(.MYI)可能不一致,手动修复耗时且不一定成功 - InnoDB 启动时若检测到未刷盘的脏页,会从
ib_logfile重放,整个过程无需人工干预
全文索引、GIS、压缩等特性不再构成选择理由
MySQL 5.6 起,InnoDB 已支持全文索引;8.0 起支持空间函数和 COMPRESSED 行格式。MyISAM 曾有的“轻量”“快”优势也早已过时——现代 SSD + 缓存机制下,InnoDB 的随机读写性能并不比 MyISAM 差,反而因 MVCC 和缓冲池设计更稳定。
真正还用 MyISAM 的场景只剩极少数:
- 只读静态数据(如城市编码表),且明确禁用
INSERT/UPDATE/DELETE - 历史遗留系统中大量使用
SELECT COUNT(*),而 MyISAM 的行数缓存确实更快(但可通过加汇总表规避) - 磁盘空间极度紧张,且确认不需要事务和崩溃安全(风险极高,不推荐)
现在新建项目几乎没理由选 MyISAM。哪怕只是临时表或日志归档表,InnoDB 的可靠性与维护成本优势也压倒性胜出。真正容易被忽略的是:MyISAM 的 AUTO_INCREMENT 在重启后可能重置,而 InnoDB 会持久化该值——这点在分库分表或 ID 生成逻辑中常引发隐性 bug。










