存储引擎
MySQL支持哪些存储引擎?
MyISAM和InnoDB有什么区别?
MyISAM 和 InnoDB 是 MySQL 历史上最著名的两个存储引擎。
一句话总结: 除非你有极特殊的理由(例如维护极老的遗留系统),否则请无脑选择 InnoDB。从 MySQL 5.5 开始,InnoDB 就已经是默认引擎了。
以下是详细的区别对比和场景分析:
1. 核心区别对比
| 特性 | InnoDB | MyISAM | 影响 |
|---|---|---|---|
| 事务支持 | 支持 (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 是绝对的首选。”