MySQL 存储引擎
MySQL 存储引擎决定了表的数据如何存储、如何建立索引、是否支持事务、使用什么锁机制以及崩溃后能否恢复。学习存储引擎的重点不是背定义,而是理解为什么生产环境默认选择 InnoDB。
查看存储引擎
查看当前 MySQL 支持的存储引擎:
SHOW ENGINES;查看某张表使用的存储引擎:
SHOW TABLE STATUS LIKE 'user';建表时指定:
CREATE TABLE user (
id BIGINT PRIMARY KEY,
username VARCHAR(64) NOT NULL
) ENGINE = InnoDB;修改已有表:
ALTER TABLE user ENGINE = InnoDB;InnoDB
InnoDB 是 MySQL 5.5 以后默认的存储引擎,也是生产环境最常用的选择。
核心特点:
- 支持事务。
- 支持行级锁。
- 支持外键。
- 支持崩溃恢复。
- 使用 B+Tree 组织索引。
- 数据按主键聚簇存储。
- 支持 MVCC,提高并发读写能力。
InnoDB 为什么适合生产
1. 支持事务
事务保证一组操作要么全部成功,要么全部失败。
典型场景:
创建订单
-> 扣减库存
-> 扣减余额
-> 写订单记录如果库存扣了但订单写入失败,数据就会不一致。事务可以在异常时回滚,保证核心数据可靠。
2. 支持行级锁
InnoDB 可以尽量只锁住需要修改的行,而不是锁整张表。
例如:
UPDATE account SET balance = balance - 100 WHERE id = 1;在索引命中的情况下,InnoDB 通常只锁 id = 1 这一行。这样其他用户修改自己的账户时不会被整表阻塞。
注意:如果 SQL 没有走索引,行锁可能退化成大量记录锁,表现上接近锁表。因此生产环境必须关注索引和执行计划。
3. 支持崩溃恢复
InnoDB 通过 redo log、undo log 等机制保证数据库异常宕机后可以恢复。
- redo log:保证已提交事务的修改不会丢。
- undo log:支持事务回滚,也支持 MVCC。
- binlog:MySQL Server 层日志,常用于主从复制和数据恢复。
这也是生产环境选择 InnoDB 的重要原因。
聚簇索引
InnoDB 表的数据本身按照主键组织成 B+Tree,这个主键索引就是聚簇索引。叶子节点保存完整行数据。
如果查询条件使用主键:
SELECT * FROM user WHERE id = 1;可以直接通过主键 B+Tree 找到整行数据。
如果使用普通索引:
SELECT * FROM user WHERE username = 'justin';普通索引叶子节点保存的是主键值,需要先通过普通索引找到主键,再回到聚簇索引查询完整行,这个过程叫回表。
MyISAM
MyISAM 是 MySQL 早期常用存储引擎,现在生产业务表一般不推荐使用。
特点:
- 不支持事务。
- 不支持行级锁,只支持表级锁。
- 不支持崩溃后的安全恢复。
- 读取性能在某些只读场景下较好。
- 支持全文索引,但现在 InnoDB 也支持全文索引。
MyISAM 适合历史只读数据、临时分析、对事务一致性要求很低的场景。但互联网业务表通常需要事务和并发写入,所以更适合 InnoDB。
InnoDB 和 MyISAM 对比
| 对比项 | InnoDB | MyISAM |
|---|---|---|
| 事务 | 支持 | 不支持 |
| 锁粒度 | 行级锁、表级锁 | 表级锁 |
| 外键 | 支持 | 不支持 |
| 崩溃恢复 | 支持 | 较弱 |
| 索引结构 | B+Tree,聚簇索引 | B+Tree,非聚簇 |
| 适合场景 | 高并发读写、核心业务表 | 只读或低一致性场景 |
如何选择
生产环境默认选择 InnoDB,除非有非常明确的理由。
选择 InnoDB 的原因:
- 需要事务。
- 需要并发写入。
- 需要数据可靠性。
- 需要主从复制和恢复能力。
- 需要和 Spring 事务配合。
不建议为了所谓“读性能”随意选择 MyISAM,因为一旦业务发展出写入、事务、恢复需求,迁移成本会更高。
常见问题
1. 为什么 InnoDB 支持事务
InnoDB 通过 undo log 支持回滚,通过 redo log 保证提交后的数据可恢复,并结合锁和 MVCC 保证并发事务下的一致性。
2. 为什么 InnoDB 使用 B+Tree
B+Tree 适合磁盘存储。它的层级低,查询时磁盘 IO 次数少;叶子节点之间有顺序指针,适合范围查询。相比普通二叉树,它更适合数据库索引。
3. 为什么主键建议自增
InnoDB 数据按主键聚簇存储。自增主键能让新数据大多追加到 B+Tree 末尾,减少页分裂。随机 UUID 作为主键会导致插入位置分散,增加页分裂和索引维护成本。
4. 什么是回表
通过普通索引查到主键后,再根据主键去聚簇索引查询完整行数据,这个过程叫回表。可以通过覆盖索引减少回表。
实践总结
MySQL 存储引擎决定表的数据组织、索引、事务和锁机制。生产环境通常选择 InnoDB,因为它支持事务、行级锁、崩溃恢复和 MVCC,适合高并发读写。
InnoDB 使用聚簇索引,数据按主键组织,普通索引查询完整行时可能需要回表。MyISAM 不支持事务和行级锁,更多适合只读或低一致性场景,现在业务表一般不推荐作为核心业务表使用。