必须用innodb:myisam不支持事务、无崩溃恢复、仅表级锁、count(*)语义错误、无外键;innodb通过redo/undo log保障acid、行级锁、事务一致性count、自动崩溃恢复及外键约束。

InnoDB 是当前 MySQL 的默认且推荐引擎,MyISAM 仅在极少数只读、静态、低并发场景下可考虑;绝大多数业务用 MyISAM 都是隐患,不是性能优化,而是埋雷。
事务支持:ACID 不是可选项,而是数据存活底线
涉及资金、订单、库存、用户状态变更等任何“全成功或全失败”逻辑,必须用 InnoDB。它靠 redo log 和 undo log 实现原子性与崩溃后自动恢复——MySQL 重启后能自己回正,无需人工干预。MyISAM 没有日志机制,异常中断后 .MYD 文件极易损坏,只能手动运行 REPAIR TABLE,修复结果不可控。
InnoDB 中每条写操作默认自动提交(autocommit=1),但高吞吐场景应显式用 BEGIN/COMMIT 包裹多语句;MyISAM 所有写都是直写磁盘,无回滚能力,UPDATE 中途失败会导致部分行已改、部分未改,状态永远不一致。
- 事务中使用临时表?
MyISAM临时表无法参与事务,会破坏整体一致性 - 应用层封装“伪事务”?不可靠,网络超时、进程崩溃、主从延迟都可能让状态分裂
锁机制:行级锁 ≠ 自动生效,索引设计决定并发效果
InnoDB 的行级锁只在查询条件命中索引(尤其是主键或唯一索引)时才真正起效;否则退化为全表锁,和 MyISAM 一样堵死。
WHERE id = ?(id 是主键)→ 锁单行WHERE status = 'pending'(status 无索引)→ 锁全表,高并发下 SHOW PROCESSLIST 里满屏 Waiting for table level lock
-
MyISAM的“并发插入”仅指INSERT追加到表尾且无其他读写时才允许,不是真正的并发写 - 写多读少场景下,
MyISAM表级锁会让吞吐量断崖式下跌,监控指标会明显异常 -
InnoDB支持SELECT ... FOR UPDATE和SELECT ... LOCK IN SHARE MODE,MyISAM完全不支持显式锁控制
索引与存储结构:聚簇索引决定物理布局,主键不是可选配置
InnoDB 必须有主键,数据按主键顺序物理存储在 .ibd 文件中;没有显式主键时,它会隐式生成一个不可见的 ROW_ID,但该值不能用于业务逻辑,也不保证单调递增。
MyISAM 数据和索引完全分离(.MYD + .MYI),主键非必需,二级索引叶子节点存的是 .MYD 中的物理偏移;InnoDB 二级索引叶子节点存的是主键值,非主键查询常需回表,因此主键不宜过长(如避免用 UUID 字符串作主键)。
-
AUTO_INCREMENT字段在InnoDB中必须是索引的第一列;MyISAM允许在联合索引中非首列递增,但极少实用 -
InnoDB的Buffer Pool同时缓存数据页和索引页;MyISAM的Key Cache只缓存索引,数据仍要频繁读磁盘 - 全文索引:MySQL 5.6+ 的
InnoDB已原生支持FULLTEXT,MyISAM的历史优势早已消失
外键与运维成本:缺失功能会持续推高开发和 DBA 负担
InnoDB 支持外键约束,能在数据库层强制参照完整性;MyISAM 把这事全甩给应用层,错一次就埋个脏数据点。
比如删除用户前,InnoDB 可设 ON DELETE CASCADE 自动清理关联订单;MyISAM 得靠应用先查再删再清理,中间任意环节出错,就会留下孤儿记录。
- 主从复制中,
MyISAM表的非事务性操作可能导致主从数据不一致,且无法通过 binlog 精确重放 -
mysqldump备份时,MyISAM需加--lock-tables,备份期间整库写入阻塞;InnoDB可用--single-transaction实现无锁热备 - MySQL 8.0 已彻底移除
MyISAM的部分系统表依赖,继续用它等于主动放弃版本升级路径
InnoDB 的行锁和性能优势,全系在索引是否被命中这一环上。没索引的 WHERE 条件,再好的引擎也救不了。











