InnoDB存储引擎架构
约 1735 字大约 6 分钟
mysqlinnodb
2025-04-30
InnoDB 是 MySQL 默认的事务型存储引擎,其架构设计围绕高并发、数据完整性和崩溃恢复展开。本文从内存结构、磁盘结构、索引组织三个维度深入剖析 InnoDB 的内部机制。
整体架构概览
InnoDB 的架构分为内存区域和磁盘区域两大部分,它们通过后台线程协同工作。
Buffer Pool
Buffer Pool 是 InnoDB 最核心的内存组件,用于缓存表数据和索引数据的页(Page)。默认页大小为 16KB。
关键特性
- LRU 管理:采用改良的 LRU 算法,将链表分为 young 区(热数据)和 old 区(冷数据),midpoint 默认在链表 5/8 处
- 预读机制:线性预读(Linear Read-Ahead)和随机预读(Random Read-Ahead)
- 多实例:通过
innodb_buffer_pool_instances分为多个实例减少锁争用
-- 查看 Buffer Pool 状态
SHOW ENGINE INNODB STATUS\G
-- 关键配置
SET GLOBAL innodb_buffer_pool_size = 8589934592; -- 8GB
SET GLOBAL innodb_buffer_pool_instances = 8;Buffer Pool 页状态流转
Change Buffer
Change Buffer 用于缓存对二级索引页的修改操作(INSERT/UPDATE/DELETE)。当目标页不在 Buffer Pool 中时,修改会先记录在 Change Buffer 中,后续该页被读入时再进行合并(merge)。
-- Change Buffer 配置
-- 可缓冲的操作类型
SET GLOBAL innodb_change_buffering = 'all'; -- all/none/inserts/deletes/changes/purges
-- Change Buffer 最大占 Buffer Pool 的比例
SET GLOBAL innodb_change_buffer_max_size = 25; -- 默认25%适用场景:写多读少的二级索引。主键索引(聚簇索引)不使用 Change Buffer,因为插入必须定位到具体位置。
Adaptive Hash Index (AHI)
InnoDB 会监控索引页的访问模式,当发现某些页被频繁以等值查询方式访问时,自动在 B+Tree 索引之上构建哈希索引,将查询复杂度从 O(log n) 降低到 O(1)。
-- 启用/禁用 AHI
SET GLOBAL innodb_adaptive_hash_index = ON;
-- 分区数,减少锁竞争
SET GLOBAL innodb_adaptive_hash_index_parts = 8;注意事项:AHI 仅对等值查询有效,范围查询无法使用。在高并发场景下,AHI 的锁竞争可能成为瓶颈,此时可考虑关闭。
Log Buffer
Log Buffer 是 Redo Log 在内存中的缓冲区,事务产生的 Redo Log 先写入 Log Buffer,再根据刷盘策略写入磁盘。
-- Log Buffer 大小,默认 16MB
SET GLOBAL innodb_log_buffer_size = 16777216;
-- 刷盘策略
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
-- 0: 每秒刷盘
-- 1: 每次提交都刷盘(最安全)
-- 2: 每次提交写到 OS cache,每秒 fsync磁盘结构:表空间体系
表空间类型对比
| 表空间类型 | 文件 | 内容 | 说明 |
|---|---|---|---|
| System Tablespace | ibdata1 | 数据字典、Change Buffer、Undo Log(旧版) | 全局共享 |
| File-Per-Table | table_name.ibd | 表数据和索引 | 每表独立文件 |
| General Tablespace | 用户定义 | 多表共享 | MySQL 5.7+ |
| Undo Tablespace | undo_001 / undo_002 | Undo Log | MySQL 8.0 独立 |
| Temporary Tablespace | ibtmp1 | 临时表 | 重启后重建 |
File-Per-Table vs System Tablespace
-- 启用独立表空间(默认开启)
SET GLOBAL innodb_file_per_table = ON;
-- 创建 General Tablespace
CREATE TABLESPACE ts1
ADD DATAFILE 'ts1.ibd'
ENGINE = InnoDB;
-- 将表放入 General Tablespace
CREATE TABLE t1 (id INT PRIMARY KEY) TABLESPACE ts1;页类型与结构
InnoDB 以页(Page)为最小磁盘 I/O 单元,默认 16KB。
常见页类型:
| 页类型 | 宏定义 | 说明 |
|---|---|---|
| 数据页 | FIL_PAGE_INDEX | B+Tree 叶子节点 |
| Undo 页 | FIL_PAGE_UNDO_LOG | Undo Log 数据 |
| 系统页 | FIL_PAGE_TYPE_SYS | 系统信息 |
| 事务系统页 | FIL_PAGE_TYPE_TRX_SYS | 事务系统数据 |
| Insert Buffer 空闲列表 | FIL_PAGE_IBUF_FREE_LIST | Change Buffer |
B+Tree 索引组织
InnoDB 使用 B+Tree 作为索引的底层数据结构,表数据按主键顺序组织在聚簇索引中。
聚簇索引与二级索引
CREATE TABLE users (
id INT PRIMARY KEY, -- 聚簇索引
name VARCHAR(50),
email VARCHAR(100),
INDEX idx_name (name), -- 二级索引,叶子节点存储 (name, id)
INDEX idx_email (email) -- 二级索引,叶子节点存储 (email, id)
);
-- 通过二级索引查询需要"回表"
-- 先在 idx_name 中找到 id,再通过聚簇索引查完整行
SELECT * FROM users WHERE name = 'Alice';
-- 覆盖索引,无需回表
SELECT id, name FROM users WHERE name = 'Alice';聚簇索引特点:
- 叶子节点存储完整的行数据
- 表数据物理上按主键排序
- 主键选择至关重要:推荐自增整数,避免 UUID(随机写导致页分裂)
二级索引特点:
- 叶子节点存储索引列值 + 主键值
- 查询需要回表(除非覆盖索引)
- 主键越大,二级索引占用空间越多
后台线程
| 线程 | 职责 |
|---|---|
| Master Thread | 负责将缓冲池中的数据异步刷新到磁盘 |
| IO Thread | 负责 AIO 回调处理(read/write/insert buffer/log) |
| Purge Thread | 回收已提交事务的 Undo Log |
| Page Cleaner Thread | 将脏页刷新到磁盘,替代 Master Thread 的部分工作 |
-- 查看 IO Thread 数量
SHOW VARIABLES LIKE 'innodb_%io_threads';
-- innodb_read_io_threads = 4
-- innodb_write_io_threads = 4
-- Purge Thread 数量
SHOW VARIABLES LIKE 'innodb_purge_threads';Doublewrite Buffer
为防止部分写失效(Partial Page Write),InnoDB 在将脏页写入数据文件之前,先将页写入 Doublewrite Buffer。
监控与诊断
-- InnoDB 引擎状态(最全面的诊断信息)
SHOW ENGINE INNODB STATUS\G
-- Buffer Pool 相关指标
SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS;
-- 表空间信息
SELECT * FROM information_schema.INNODB_TABLESPACES;
-- 当前事务
SELECT * FROM information_schema.INNODB_TRX;
-- 锁等待
SELECT * FROM performance_schema.data_lock_waits;总结
InnoDB 的架构设计体现了几个核心思想:
- 缓冲思想:Buffer Pool、Change Buffer、Log Buffer 均通过内存缓冲减少磁盘 I/O
- WAL 原则:先写日志(Redo Log)再写数据,保证崩溃恢复
- 写时复制/延迟写入:Change Buffer 延迟合并,Purge Thread 延迟回收
- 数据保护:Doublewrite Buffer 防止部分写失效,Checksum 校验数据完整性
理解这些架构设计,是优化 MySQL 性能和排查问题的基础。
贡献者
更新日志
9f6c2-feat: organize wiki content and refresh site setup于