跳到主要内容

存储引擎

MySQL支持哪些存储引擎?​

MyISAM和InnoDB有什么区别?​

MyISAM 和 InnoDB 是 MySQL 历史上最著名的两个存储引擎。

一句话总结: 除非你有极特殊的理由(例如维护极老的遗留系统),否则请无脑选择 InnoDB。从 MySQL 5.5 开始,InnoDB 就已经是默认引擎了。

以下是详细的区别对比和场景分析:

1. 核心区别对比​

特性InnoDBMyISAM影响
事务支持支持 (ACID)不支持InnoDB 适合对数据完整性要求高的业务(如支付)。
锁机制行级锁 (Row Lock)表级锁 (Table Lock)InnoDB 支持高并发写入;MyISAM 一写就锁整张表,并发极差。
外键支持不支持InnoDB 能保证数据参照完整性。
崩溃恢复支持 (Redo Log)不支持宕机后,InnoDB 能自动恢复;MyISAM 容易损坏,需手动修复。
COUNT(*)慢 (需扫描全表)极快 (存了计数器)MyISAM 存了总行数,不带 WHERE 条件查总数瞬间返回。
索引结构聚簇索引 (数据和索引在一起)非聚簇索引 (数据和索引分离)InnoDB 根据主键查询效率极高;MyISAM 查询需回表(除非覆盖索引)。
存储文件.frm (表结构) + .ibd (数据+索引).frm + .MYD (数据) + .MYI (索引)MyISAM 物理文件分得更开。

2. 深度解析关键差异​

A. 锁机制与并发 (最痛的点)​
  • MyISAM (表锁): 假设你在修改第 1 行数据,MyISAM 会把整张表锁住。此时,其他人想读取第 1000 行数据,也必须等待。这导致在写多读多的场景下,性能会急剧下降。
  • InnoDB (行锁): 你修改第 1 行,InnoDB 只锁第 1 行。其他人可以照常读取或修改第 1000 行。这就允许了高并发。
B. 事务与安全​
  • InnoDB: 具有“提交”、“回滚”和“崩溃恢复”能力。如果执行一半断电了,重启后 InnoDB 会根据日志(Redo Log)恢复数据,保证不丢数据、不坏数据。
  • MyISAM: 它是“原子性”的贫困户。如果执行一半断电,表可能直接损坏,需要运行 REPAIR TABLE,且数据可能丢失。
C. 查询性能 (关于"MyISAM 读更快"的谣言)​
  • 早年间(MySQL 5.0 时代),MyISAM 在纯读场景下确实比 InnoDB 快。
  • 但随着 MySQL 5.6/5.7/8.0 的优化,InnoDB 在读性能上已经赶上甚至超越了 MyISAM。加上现代硬件(SSD)的普及,InnoDB 的缓冲池(Buffer Pool)机制能更好地利用内存。
  • 唯一例外: SELECT COUNT(*) FROM table(不带 WHERE 条件)。MyISAM 记了一个变量,直接返回;InnoDB 需要一行行去数(因为有 MVCC 多版本控制,它不知道具体有多少行对当前事务可见)。

3. 场景选择​

什么时候选 InnoDB? (99.9% 的情况)​
  • 需要事务支持: 涉及钱、订单、库存等必须保证数据一致性的业务。
  • 高并发环境: 有很多用户同时在一个表里写数据、改数据。
  • 需要容灾恢复: 不希望数据库意外重启后数据损坏。
  • 通用业务: 用户表、日志表、商品表等。
什么时候选 MyISAM? (0.1% 的情况)​
  • 极度陈旧的系统: 代码里依赖了 MyISAM 的特性,且迁移成本过高。
  • 只读数据/归档数据: 某些表一旦写入就不再修改,且不做复杂的关联查询,只用来做报表分析,且极度在意磁盘空间(MyISAM 压缩后通常比 InnoDB 小),且不在乎数据丢失风险。
  • Count(*) 狂魔: 业务极度依赖 select count(*) 且无法使用 Redis 等缓存层解决(但这通常是架构设计问题)。

4. 总结​

在现在的开发面试和实际工作中: 忘记 MyISAM,拥抱 InnoDB。

如果面试官问:“MyISAM 有什么优点?” 你可以回答:“它在不带 WHERE 条件的 COUNT(*) 查询上非常快,且早期版本在纯读场景下有优势,表文件可以直接拷贝备份。但在现代高并发、高可靠的业务需求下,InnoDB 是绝对的首选。”