必须用innodb;myisam仅适用于离线归档且接受不可修复风险的极少数场景,因其不支持事务、表级锁、崩溃易损坏、全文索引等优势已过时,主流版本默认禁用。

只要业务涉及“要么全成、要么全败”,比如资金扣减、库存变更、权限同步,必须用 InnoDB;MyISAM 仅在极少数只读、无并发、不关心崩溃后数据一致性的场景下可考虑,但连这都要先确认 MySQL 版本是否还默认启用它(2026 年多数发行版已禁用 MyISAM 插件)。
事务支持:没 BEGIN 就别碰 MyISAM
MyISAM 对 BEGIN、COMMIT、ROLLBACK 完全无视——语句一执行就落盘,中间崩溃等于半截数据写进去。InnoDB 则靠 redo log 和 undo log 实现真正的 ACID:
- 转账失败时,
UPDATE回滚后账户余额恢复原状,不会出现“张三扣了钱、李四没到账” - 批量导入中途断电,重启后自动恢复到最近一次
COMMIT状态 -
AUTO_INCREMENT在事务中回滚后,InnoDB 会还原自增值(MySQL 8.0+ 行为更稳定,但需实测验证)
锁机制:高并发写入场景下,MyISAM 是阻塞源头
UPDATE users SET status=1 WHERE id=123 这种精准条件,在 InnoDB 中只锁一行;MyISAM 则直接锁整张 users 表,后续所有读写全部排队。
- 即使只是后台定时任务跑
INSERT INTO log_table,只要表上有其他查询,MyISAM 就可能卡住整个页面加载 - 模糊查询如
WHERE name LIKE "%abc%"在 InnoDB 中若无索引,也会升级为全表扫描+行锁(不是表锁),而 MyISAM 没有“升级”概念——它本来就是表锁 - MyISAM 写锁优先级高于读锁,一个新
INSERT能插队到 10 个等待的SELECT前面,导致读饥饿
COUNT(*) 和崩溃恢复:快 ≠ 正确,停机 ≠ 安全
MyISAM 的 COUNT(*) 快,是因为它缓存了行数变量;InnoDB 每次都按事务隔离级别算可见行数——这才是符合语义的结果。
-
SELECT COUNT(*) FROM orders WHERE status = 'paid':两者都要走索引扫描,性能差异可忽略,但 MyISAM 结果不保证事务一致性 - 服务器突然断电:InnoDB 重启后自动重放
redo log,MyISAM 可能损坏,需人工REPAIR TABLE,且修复过程可能丢数据 -
myisamchk工具必须停服使用,否则可能加剧损坏;而 InnoDB 的崩溃恢复完全自动化,无需 DBA 干预
全文索引和空间函数:MyISAM 最后几个“优势”也已过时
MySQL 5.7 起,InnoDB 已原生支持全文索引;8.0+ 支持 GIS 函数(如 ST_Contains)。MyISAM 曾经唯一的硬优势基本消失。
- MyISAM 的
FULLTEXT索引不支持事务,更新时需重建,无法实时生效 - 压缩表(
myisampack)生成只读文件,一旦启用,INSERT直接报错The table is read only - 当前主流部署(如 Percona Server、MariaDB 11+、MySQL 8.4 LTS)默认关闭 MyISAM 插件,
SHOW ENGINES中显示DISABLED
真正需要选 MyISAM 的场景,现在几乎只剩一种:离线归档表,且明确要求用 myisampack 压缩 + LOAD DATA INFILE 批量导入,同时接受不可修复风险。其余所有在线系统、CMS 后台、日志分析表,都应默认用 InnoDB,哪怕只是单用户本地开发环境——因为行为一致性比“省几毫秒”重要得多。











