innodb 是绝大多数业务的默认且合理选择,因其支持事务、外键和崩溃恢复,能保障原子性操作(如订单创建+库存扣减+日志记录)的一致性;myisam 无事务机制,写锁表、易损坏、恢复不可控,仅适用于读多写少且无一致性要求的静态场景。

InnoDB 是绝大多数业务的默认且合理选择,除非你明确知道为什么不用它。
需要事务、外键或崩溃恢复时必须用 InnoDB
只要业务涉及“原子性操作”,比如订单创建+库存扣减+日志记录这三步必须全成功或全失败,就必须用 InnoDB。MyISAM 没有 ROLLBACK,一旦中间出错,数据就处于不一致状态。
常见错误现象:UPDATE 执行一半失败,表里只更新了部分行,应用层无法感知或回退;数据库重启后 MyISAM 表可能报 crashed,需手动 REPAIR TABLE。
- 金融、电商、用户账户类系统,一律用
InnoDB - 哪怕当前没用外键,未来可能加关联约束,
InnoDB提前预留能力 -
InnoDB的redo log和undo log是崩溃后自动恢复的基础设施,MyISAM 没有等价机制
读多写少且无事务需求时,MyISAM 可能更快但风险明显
比如静态配置表、只读日志归档表(如 sys_log_202501),MyISAM 的 COUNT(*) 不扫表、索引更轻量、内存占用更低——但这优势正被现代硬件和 InnoDB 优化持续削弱。
容易踩的坑:
-
MyISAM写操作会锁整张表,哪怕只是INSERT一条记录,其他所有读写都得排队 - 并发稍高(>10 QPS 写入)时,响应延迟会陡增,监控上表现为
Table_locks_waited持续上升 - 服务器异常断电后,
MyISAM表损坏概率远高于InnoDB,且修复过程不可控
InnoDB 的 COUNT(*) 慢不是 bug,是设计取舍
因为 InnoDB 支持 MVCC,不同事务看到的行数可能不同,所以无法像 MyISAM 那样维护一个全局计数器。这不是性能缺陷,而是事务一致性的代价。
实操建议:
- 真要高频查总数?加个冗余字段(如
total_count),在事务里同步更新 - 用近似值够用?查
information_schema.TABLES里的TABLE_ROWS(误差可能达 40%) - 避免在大表上直接跑
SELECT COUNT(*)—— 无论引擎,都是全表扫描
别忽略 SHOW ENGINES 和实际负载验证
有些旧部署里 MyISAM 被禁用,或 InnoDB 因参数配置不当(如 innodb_buffer_pool_size 过小)表现反常。光看文档对比没用,得看自己实例。
关键动作:
- 执行
SHOW ENGINES;确认InnoDB的Support是DEFAULT或YES - 查
SHOW TABLE STATUS LIKE 'xxx';看当前表实际用的引擎,别信建表语句里没写的默认值 - 压测时对比
Handler_read_*和Innodb_row_lock_waits,比理论参数更有说服力
MyISAM,不如直接迁到 Archive 引擎或冷数据归档服务。引擎选型只是起点,不是终点。











