这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 InnoDB 是事务存储引擎,负责页面存储、B+Tree、行操作、事务、锁、MVCC、日志、恢复和后台维护。
12.1 总体结构
ha_innobase
-> row module
|-- btr: B+Tree
|-- page: page layout
|-- rem: record format
|-- buf: buffer pool
|-- lock: row/table locks
|-- trx: transaction
|-- undo: undo log
|-- log: redo log
|-- mtr: physical consistency
+-- fil: tablespace
12.2 目录地图
| 目录 | 职责 |
|---|---|
storage/innobase/btr/ |
B+Tree 操作 |
storage/innobase/page/ |
页面结构 |
storage/innobase/rem/ |
记录格式 |
storage/innobase/row/ |
行读写与更新 |
storage/innobase/buf/ |
Buffer Pool |
storage/innobase/ibuf/ |
Change Buffer |
storage/innobase/lock/ |
锁系统 |
storage/innobase/trx/ |
事务 |
storage/innobase/undo/ |
Undo |
storage/innobase/log/ |
Redo |
storage/innobase/fil/ |
表空间 |
storage/innobase/dict/ |
引擎数据字典 |
storage/innobase/purge/ |
清理 |
storage/innobase/row/row0mysql.cc |
handler 桥接 |
12.3 数据组织
Instance
-> tablespace
-> segments
-> extents
-> pages
-> records
默认页大小 16KB:
SHOW VARIABLES LIKE 'innodb_page_size';
聚簇索引按主键组织数据;二级索引叶子存主键值,查询非索引列需要回表。
12.4 事务路径
BEGIN
-> assign trx
-> read / modify rows
|-- lock records
|-- write undo
+-- write redo in mtr
-> prepare
-> write binlog
-> commit
-> release locks
事务模块与 undo、redo、锁和 purge 紧耦合,需要整体阅读。
12.5 后台线程
| 线程 | 职责 |
|---|---|
| master thread | 统筹后台任务 |
| purge thread | 清理 delete-mark 和 undo |
| page cleaner | 刷脏页 |
| read ahead / IO thread | 异步 IO |
| log flusher / writer | redo 日志刷盘 |
| dict stats | 统计收集 |
12.6 观测入口
SHOW ENGINE INNODB STATUS;
SELECT * FROM information_schema.innodb_trx;
SELECT * FROM information_schema.innodb_buffer_page_lru LIMIT 10;
SHOW GLOBAL STATUS LIKE 'Innodb_%';
源码定位:
rg "Innodb_buffer_pool_read_requests" storage/innobase
rg "row_lock_current_waits" storage/innobase
本章小结
InnoDB 可以按存储结构、行操作、事务并发、日志恢复和后台线程五条线阅读。先建立模块地图,再沿一条 SQL 的读写路径进入源码,能显著降低复杂度。
思考题
- 聚簇索引和二级索引的存储关系是什么?
- InnoDB 哪些模块参与一次 UPDATE?
- purge thread 清理什么数据?
- 如何从 InnoDB 状态变量定位源码?
- 为什么事务模块要与 undo、redo、lock 一起读?