存储引擎的选择:InnoDB vs MyISAM
大家好,我是一名拥有10年以上经验的DBA老兵。
做这个系列,源于一个朴素的愿望:把踩过的坑、总结的经验系统化输出,希望能帮到刚入行或想进阶的兄弟们。
让我们开始今天的第2天内容。
背景引入
💡 说白了:选错存储引擎,就像用自行车拉货——不是不行,是费劲。
很多同学建表时不指定存储引擎,默认就是 InnoDB。但你知道吗?在 MySQL 5.5 之前,默认是 MyISAM。
今天的目标:搞清楚 InnoDB 和 MyISAM 的区别,面试必问!
核心概念
什么是存储引擎?
MySQL 的特点是插件式存储引擎,数据怎么存、怎么读,完全由存储引擎决定。
-- 查看MySQL支持的存储引擎及执行结果
> SHOW ENGINES;
+------------------+---------+-------------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+------------------+---------+-------------------------------------------------------------------+--------------+------+------------+
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+------------------+---------+-------------------------------------------------------------------+--------------+------+------------+
💡 说白了:存储引擎就是"仓库管理员", InnoDB 是现在的标配,曾经的 MyISAM 是老江湖。
InnoDB vs MyISAM 核心区别
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事务支持 | ✅ 支持 ACID | ❌ 不支持 |
| 锁粒度 | 行锁(Row Lock) | 表锁(Table Lock) |
| 外键 | ✅ 支持 | ❌ 不支持 |
| 崩溃恢复 | ✅ 自动恢复 | ❌ 需手动修复 |
| 存储方式 | 聚簇索引 | 非聚簇索引 |
| COUNT(*) | 需要遍历索引 | 直接读取行数 |
| 适用场景 | 业务数据、事务需求 | 日志、只读数据 |
面试必问:
- InnoDB 和 MyISAM 有什么区别?
- 为什么现在都用 InnoDB?
- MyISAM 还有人用吗?什么时候用?
📝 面试解答:
Q: InnoDB 和 MyISAM 有什么区别?
最核心的区别:InnoDB 支持事务,MyISAM 不支持。
- InnoDB 是行锁,高并发下性能好;MyISAM 是表锁,写操作会锁整张表
- InnoDB 支持外键,MyISAM 不支持
- InnoDB 有崩溃自动恢复,MyISAM 坏了可能需要手动修复
- InnoDB 主键索引就是数据,MyISAM 主键索引是指向数据的指针
Q: 为什么现在都用 InnoDB?
因为绝大多数业务都需要事务支持。转账、订单、库存...没有事务,数据分分钟错乱。
而且 InnoDB 的行锁在并发场景下性能碾压 MyISAM 的表锁。
Q: MyISAM 还有人用吗?什么时候用?
极少数场景:
- 只读/历史数据:不需要事务,写入一次就不变了
- 日志表:写入频繁,但不需要事务
- COUNT(*) 频繁:MyISAM 整表行数存内存里,COUNT(*) 特别快(但 InnoDB 8.0 也优化了)
- 空间紧张:MyISAM 索引更小
如何选择?
-- 查看表的存储引擎
SHOW TABLE STATUS FROM database_name LIKE 'table_name';
-- 创建表时指定存储引擎
CREATE TABLE t1 (...) ENGINE=InnoDB;
CREATE TABLE t2 (...) ENGINE=MyISAM;
💡 无脑选 InnoDB,除非有特殊理由。
💡 AI辅助选择:让AI根据你的业务场景推荐存储引擎,直接问:
"我的业务是XXX,需要事务/高并发吗?选InnoDB还是MyISAM?"💡 个人Skill建议:在你的Skill里加一个建表规范检查,检查项包括:
- 存储引擎是否指定为InnoDB
- 主键是否自增
- 字符集是否为utf8mb4
- 是否有create_time/update_time时间字段
| 业务场景 | 推荐引擎 | 原因 |
|---|---|---|
| 订单/交易/用户 | InnoDB | 必须事务,行锁高并发 |
| 日志/审计表 | InnoDB | 8.0后性能足够,可靠性更重要 |
| 只读报表/历史数据 | MyISAM | 仅追加写无并发读写要求,定期归档 |
| 临时缓存表 | MEMORY | 内存存储,速度最快 |
实战案例
场景一:事务回滚
InnoDB 支持事务,可以回滚:
-- 事务测试及执行结果
BEGIN;
INSERT INTO user (name) VALUES ('Tom');
ROLLBACK;
-- 数据被回滚了
MyISAM 不支持事务,ROLLBACK 对它无效:
-- InnoDB 表:事务可以回滚
BEGIN;
INSERT INTO t_innodb (name) VALUES ('Tom');
ROLLBACK;
SELECT COUNT(*) FROM t_innodb; -- 结果:0(数据被回滚了)
-- MyISAM 表:ROLLBACK 对 MyISAM 无效,数据还在
BEGIN;
INSERT INTO t_myisam (name) VALUES ('Tom');
ROLLBACK;
SELECT COUNT(*) FROM t_myisam; -- 结果:1(MyISAM 不支持事务,ROLLBACK 无效)
场景二:并发更新
InnoDB 行锁,两个事务可以同时更新不同行:
-- 行锁测试及执行结果
-- 事务1一个连接:UPDATE user SET name='A' WHERE id=1;
-- 事务2另开一个连接:UPDATE user SET name='B' WHERE id=2; -- 同时执行成功
MyISAM 表锁,写操作会锁整张表:
-- InnoDB 行锁:两个连接同时更新不同行,互不阻塞
-- 连接1:
BEGIN;
UPDATE user SET name='A' WHERE id=1; -- 只锁 id=1 这一行
-- 连接2(同时执行):
UPDATE user SET name='B' WHERE id=2; -- ✅ 不阻塞,更新的不是同一行
-- MyISAM 表锁:用 LOCK TABLES 显式持锁才能演示阻塞
-- 连接1:
LOCK TABLES user WRITE;
UPDATE user SET name='A' WHERE id=1; -- 锁整张表
-- 连接2(同时执行):
UPDATE user SET name='B' WHERE id=2; -- ❌ 被阻塞,必须等连接1释放锁
-- 连接1:
UNLOCK TABLES; -- 释放锁后,连接2才能执行
避坑指南
⚠️ 真实踩过的坑:
建表不指定 ENGINE,默认可能是 MyISAM
- MySQL 5.5 之前默认 MyISAM,5.5 之后默认 InnoDB
- 有一些公司规范禁止指定存储引擎,由DBA统一把控
MyISAM 崩溃数据丢失
- MyISAM 没有崩溃恢复,异常关机可能损坏
- 重要业务数据千万别用 MyISAM
COUNT(*) 慢?
- MyISAM 确实快,但 InnoDB 8.0 优化后也不差
- 别为了 COUNT(*) 快选 MyISAM,不值得
- InnoDB 8.0 优化后,COUNT(*) 会选最小的二级索引遍历,不再全表扫描
思考题
🤔 互动时间:
- 如果某个表不需要事务,就是存日志,选什么引擎?为什么?
- 为什么阿里规约要求「表必须使用 InnoDB 存储引擎」?
总结
🎯 面试考点
- InnoDB vs MyISAM 核心区别:事务、行锁、崩溃恢复
- InnoDB 支持事务、Row Lock、外键
- MyISAM 只支持表锁,无事务,适用于只读场景
- 无脑选 InnoDB,除非有特殊理由
💡 AI实战建议:让自己的AI助手记住建表规范检查清单,每次写CREATE TABLE时自动检查
下期预告:InnoDB存储引擎核心结构 —— 深入底层
【合集】:每天一个MySQL知识点,百日打怪升级
有问题欢迎评论区交流,明天见!