Buffer Pool 与 LRU:frame、flush 列表与 young/old 分区
把 innodb_buffer_pool_size 调到物理内存的
80%,TPS 反而下降——SHOW ENGINE INNODB STATUS 里
Buffer pool hit rate 仍然很高,但 checkpoint
期间 pending flush 暴涨,业务线程在
log flush 和 buf pool wait
上排队。问题往往不在「缓存不够大」,而在 flush
列表跟不上脏页产生速度,或 全表扫描把 young
区热页挤进 old 区再被逐出。
InnoDB 的 Buffer Pool 不是单一 LRU 链表:它同时维护
LRU(替换)、Free(空闲
frame)、Flush(按修改 LSN
排序的脏页)三套列表,并按
innodb_old_blocks_pct 划分 young/old 子区。Page
cleaner 线程批量刷 flush 列表;连接线程通过
buf_page_get() 拿页、改页、挂到 flush
列表。本文以 MySQL
8.0.36(storage/innobase/buf/)为主线,对照
PG
Buffer Manager 的 Clock Sweep 与 pin 协议。
一、Buffer Pool 在 UPDATE 路径上的位置
1.1 从 handler 到 frame
一次 UPDATE 进入 InnoDB
后,数据页访问大致经过:
ha_innobase::update_row()
→ row_update_for_mysql()
→ btr_cur_search_to_nth_level() // B+Tree 定位
→ buf_page_get_gen() // 拿 Buffer Pool 中的页
→ buf_LRU_get_free_block() // miss 时分配 frame
→ fil_io() / os_aio() // 异步读盘
→ mtr_start() / 修改页 / mtr_commit() // 写 redo,挂 flush 列表
Buffer Pool 是
数据页在内存中的唯一入口:聚簇索引、二级索引、undo
页、change buffer 页都缓存为 buf_block_t 中的
16KB frame(默认 innodb_page_size=16384)。
1.2 与 redo、doublewrite 的衔接
页在内存中被修改时:
- Mini-Transaction(mtr) 把字节级变更写入 redo log buffer(第 4 章)
- 页的
oldest_modification与 flush 列表 关联——决定 checkpoint 能推进到哪里 - 脏页落盘前经 doublewrite 保护(第 6 章)
因此 Buffer Pool 状态直接决定崩溃恢复窗口与 checkpoint IO 形态——不是「命中率」一个指标能概括的。
flowchart LR
GET[buf_page_get] --> PIN[fix / unfix 计数]
PIN --> MTR[mtr 修改页]
MTR --> REDO[redo log buffer]
MTR --> FL[flush 列表]
FL --> PC[page cleaner flush]
PC --> DW[doublewrite]
DW --> DATA[(.ibd 表空间)]
二、物理布局:instance、chunk、frame
2.1 多实例降低 latch 争用
innodb_buffer_pool_instances(默认 8,与 CPU
核数相关)把总 Buffer Pool 拆成多个
buf_pool_t 实例。页面 hash 到实例:
buf_pool_index = hash(space_id, page_no) % srv_buf_pool_instances
每个实例有独立的 LRU、Free、Flush 列表与 page
hash——高并发下减少 buf_pool_mutex
争用。实例过少时,多线程同时 buf_page_get
同一实例会成为瓶颈;实例过多则每实例容量变小,大工作集难以缓存。
| 配置项 | 默认值(8.0) | 作用 |
|---|---|---|
innodb_buffer_pool_size |
128MB(需调大) | 总字节数 |
innodb_buffer_pool_instances |
8 | 实例个数 |
innodb_buffer_pool_chunk_size |
128MB | 单次扩展 chunk 大小 |
innodb_page_size |
16384 | 每 frame 字节数 |
2.2 chunk 与 block
内存按 chunk
分配(buf0buf.cc 中
buf_pool_create())。每个 chunk 包含连续
buf_block_t 数组,每个 block 含:
| 成员 | 含义 |
|---|---|
frame |
16KB 页数据 |
page |
buf_page_t 元数据(state、LRU 节点、hash
节点) |
lock |
buffer block rw_lock |
mutex |
block 级互斥 |
buf_block_t 与 buf_page_t
的关系:索引页/数据页通过 buf_page_t 挂入
LRU/Flush;buf_block_t 是物理 frame 容器。
2.3 page hash 表
(space_id, page_no) → buf_page_t* 映射在
per-instance hash
表(buf_pool_t::page_hash)。buf_page_get_gen()
先 hash 查找;未命中则 buf_LRU_get_free_block()
拿空闲 frame,再发起读 I/O。
源码路径(8.0.36):
storage/innobase/include/buf0buf.h:buf_block_t、buf_page_t、buf_pool_tstorage/innobase/buf/buf0buf.cc:buf_page_get_gen()、buf_pool_init()storage/innobase/buf/buf0buddy.cc:compressed page buddy 分配
三、buf_page_t 状态与 fix 计数
3.1 页面状态位
buf_page_t::state
编码页面生命周期(简化):
| 状态 | 含义 |
|---|---|
BUF_BLOCK_POOL_FREE |
frame 在 free 列表 |
BUF_BLOCK_ZIP_PAGE |
压缩页 |
BUF_BLOCK_FILE_PAGE |
普通文件页,已读入或正在读 |
BUF_BLOCK_MEMORY |
内存临时结构 |
BUF_BLOCK_REMOVE_HASH |
正在从 hash 移除 |
3.2 fix 计数(类似 PG pin)
buf_fix_count 表示有多少线程
fix 了该页——fix 期间页面不能被 LRU
驱逐。buf_page_get() 增加
fix;buf_page_release() 减少。
与 PG PinBuffer / ReleaseBuffer
对照:
| 操作 | InnoDB | PostgreSQL |
|---|---|---|
| 拿页 | buf_page_get + fix++ |
ReadBuffer + pin |
| 放页 | buf_page_release + fix– |
ReleaseBuffer |
| 内容互斥 | rw_lock on block |
content_lock LWLock |
| 驱逐保护 | fix_count > 0 | refcount > 0 |
fix 泄漏会导致 frame 永久占用——最终
Buffer pool hit rate
下降、free list 耗尽。
3.3 状态机
stateDiagram-v2
direction LR
[*] --> Free: 初始化
Free --> Cached_Clean: 读盘完成
Cached_Clean --> Cached_Dirty: mtr 修改
Cached_Dirty --> Flushing: page cleaner / LRU flush
Flushing --> Cached_Clean: 写盘完成
Cached_Clean --> Free: LRU 驱逐且 clean
Cached_Dirty --> Free: 先 flush 再驱逐
四、LRU 列表:young 与 old 子区
4.1 为什么不是纯 LRU
纯 LRU 下,一次大表全扫描会把所有扫描过的页插入 LRU 头部——污染热数据。InnoDB 把 LRU 分为:
- young 区:最近频繁访问的页(默认占 LRU
的 ~75%,由
innodb_old_blocks_pct控制 old 区起点) - old 区:新读入或「可疑一次性」访问的页
首次读入的页进入 old 区头部(LRU
的「冷端附近」)。若在
innodb_old_blocks_time(毫秒,默认
1000)内再次访问,则提升到 young 区;否则在 old
区内移动或被淘汰。
4.2 innodb_old_blocks_pct
innodb_old_blocks_pct 默认 37:LRU
列表长度中约 37% 为 old 子列表。调大 old 区 → 扫描页更集中在
cold 区,减少挤出热页;调小 → young 区更大,适合扫描较少的
OLTP。
| 场景 | 建议方向 |
|---|---|
| 定期大报表扫描 + 热 OLTP | 增大 innodb_old_blocks_pct 或优化扫描
SQL |
| 纯 OLTP、无大扫描 | 可保持默认或略减小 old 区 |
| 备份工具顺序读全库 | 临时调大 old 区或限流备份 |
源码:buf/buf0lru.cc 中
buf_LRU_add_block()、buf_page_make_young()。
4.3 LRU 淘汰路径
当 free 列表为空且需要新 frame:
buf_LRU_get_free_block()
→ 尝试 free 列表
→ buf_LRU_scan_and_flush_or_remove_last() // 从 LRU 尾扫描
→ 若页 dirty 且可 flush → buf_flush_page()
→ 若页 clean 且 fix_count=0 → 从 hash 移除,加入 free
关键:淘汰 dirty 页必须先写盘(或加入
flush 队列)——与 PG Clock Sweep 遇到 dirty buffer 先
FlushBuffer() analogous。
五、Flush 列表与 oldest_modification
5.1 为什么需要 flush 列表
LRU 按 访问时间 排序;崩溃恢复与
checkpoint 需要按 修改 LSN
顺序刷脏页。Flush 列表按
oldest_modification(页上最早未刷盘的修改
LSN)升序链接——队首是 LSN 最小的脏页。
checkpoint 推进时,log checkpointer 需要保证:已刷盘的数据页 LSN 覆盖范围 与 redo 可回收范围一致。flush 列表队首 LSN 是「最旧脏页」的上界信号。
5.2 buf_flush_page_coordinator
Page cleaner
线程(innodb_page_cleaners,默认 4)由
coordinator 协调:
buf_flush_page_coordinator()
→ buf_flush_LRU() // LRU 尾 too old dirty 页
→ buf_flush_list() // 从 flush 列表批量刷
→ 根据 redo 压力调节 batch 大小
连接线程也可能在 LRU 淘汰路径上同步 flush single
page——类似 PG buffers_backend
升高时的症状。
5.3 与 checkpoint LSN 的关系
| 变量 | 含义 |
|---|---|
log_lsn |
当前 redo 写入位置 |
checkpoint_lsn |
崩溃恢复起点 |
页 newest_modification |
页上最新修改 LSN |
| flush 列表队首 | 最旧未刷脏页的 LSN |
若 flush 列表过长 → checkpoint 无法推进 → redo 文件循环使用受阻 → 可能 stall 用户线程(第 4、10 章)。
sequenceDiagram
participant THD as 连接线程
participant BP as Buffer Pool
participant FL as Flush 列表
participant PC as Page Cleaner
participant DW as Doublewrite
THD->>BP: mtr 修改页
BP->>FL: 插入/更新 oldest_modification
PC->>FL: 取 LSN 最小批次
PC->>DW: 写 doublewrite
PC->>BP: 写表空间文件
PC->>FL: 移除已刷页
六、buf_page_get_gen 完整路径
6.1 调用链(简化)
// storage/innobase/buf/buf0buf.cc — 逻辑结构,非逐字摘录
buf_page_get_gen(space_id, page_no, ...)
→ buf_page_hash_get() // hash 命中?
→ 命中: buf_page_make_young() // LRU 提升策略
→ 未命中: buf_LRU_get_free_block()
→ buf_read_page_low() // 同步或 aio 读
→ 返回 buf_block_t*buf_read_page_low() 根据
innodb_read_io_threads 提交到 read aio
队列;读完成后 io_handler_thread 回调
buf_page_io_complete()。
6.2 预读(Read-ahead)
两种预读(buf0rea.cc):
| 类型 | 触发 | 行为 |
|---|---|---|
| 线性预读 | 顺序访问同一 extent 相邻页 | 读入 extent 内后续页 |
| 随机预读 | 同一 extent 内多页被访问 | 读入整个 extent |
预读页进入 old 区——若预读浪费,仅污染 old 区,配合
innodb_old_blocks_pct 可缓解。
配置:
innodb_read_ahead_threshold:线性预读阈值innodb_random_read_ahead:是否启用随机预读
6.3 压缩页
ROW_FORMAT=COMPRESSED 页可能小于 16KB,使用
buddy allocator(buf0buddy.cc)在 frame
内管理。解压/压缩路径增加 CPU 与 latch 开销——Buffer Pool
监控需区分 buf_pool->n_pend_unzip。
七、Free 列表与 Buffer Pool 扩展
7.1 free 列表
新分配或从 LRU 驱逐的 clean frame 进入 free
列表。buf_LRU_get_free_block()
优先消费 free 列表;为空则扫描 LRU 尾。
7.2 动态 resize(8.0)
innodb_buffer_pool_size
在线调整(有限支持)通过增加/释放 chunk 实现。resize
期间可能有短暂性能波动——生产环境应在低峰规划,并监控
Innodb_buffer_pool_resize_status。
7.3 buffer pool dump/load
innodb_buffer_pool_dump_at_shutdown /
innodb_buffer_pool_load_at_startup
把热页页号列表持久化到 #ib_buffer_pool
文件,重启后异步预热。对重启后延迟敏感的业务有价值;大 BP 时
load 可能产生 IO 风暴。
八、监控与诊断字段
8.1 SHOW ENGINE INNODB STATUS
BUFFER POOL AND MEMORY 段关键字段(需在本地实例验证具体数值):
| 字段 | 含义 |
|---|---|
Buffer pool size |
总页数 |
Free buffers |
free 列表长度 |
Database pages |
缓存中的文件页数 |
Old database pages |
old 子区页数 |
Modified db pages |
脏页数 |
Pending reads/writes |
未完成 aio |
LRU len / Free len / Flush list length |
三列表长度 |
Modified db pages 持续接近
Buffer pool size → flush
跟不上;Free buffers 长期为 0 →
淘汰压力大。
8.2 Performance Schema / Information Schema
-- 需本地验证
SELECT POOL_ID, POOL_SIZE, FREE_BUFFERS, DATABASE_PAGES,
OLD_DATABASE_PAGES, MODIFIED_DB_PAGES
FROM information_schema.INNODB_BUFFER_POOL_STATS;SELECT NAME, COUNT
FROM information_schema.INNODB_METRICS
WHERE NAME LIKE 'buffer%'
ORDER BY NAME;8.3 Global Status
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%';关注:
Innodb_buffer_pool_reads:物理读次数(miss)Innodb_buffer_pool_read_requests:逻辑读请求- 命中率 \(\approx 1 - \frac{\text{reads}}{\text{read\_requests}}\)
命中率高但 Innodb_buffer_pool_pages_dirty
比例高 → 仍是 flush/checkpoint 问题,不是 BP 太小。
九、实验(需本地验证)
以下实验需 MySQL 8.0.36 实例;本仓库写作环境未安装 MySQL,不粘贴命令输出。
9.1 观察 young/old 与命中率
-- 记录基线
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%';
SHOW ENGINE INNODB STATUS\G
-- 执行 sysbench 只读预热
-- sysbench oltp_read_only --tables=10 --table-size=100000 run
-- 再执行一次大表全扫描
-- SELECT COUNT(*) FROM sbtest.sbtest1;
-- 再次查看 STATUS,对比 Old database pages、Modified db pages预期(方法推导):全扫描后
Old database pages 上升;若
innodb_old_blocks_time 内无二次访问,这些页在
old 区被淘汰而不影响 young 热页。
9.2 innodb_old_blocks_pct A/B
SET GLOBAL innodb_old_blocks_pct = 20;
-- 重复扫描测试,记录 read_requests/reads
SET GLOBAL innodb_old_blocks_pct = 60;
-- 同样 workload 再测对比 OLTP 混合负载下热页挤出是否缓解——需相同数据规模与并发度,至少 3 次取中位数。
9.3 脏页比例与 checkpoint
SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct';
SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct_lwm';
-- 写入压力:sysbench oltp_write_only
-- 观察 Modified db pages / Buffer pool size 比值与 Log sequence number 段innodb_max_dirty_pages_pct(默认 90)控制
page cleaner 开始积极 flush 的脏页比例阈值。
9.4 实例数与 latch
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
-- 高并发 oltp_read_write 下对比 instances=1 vs 8 的 TPS 与 mutex 等待
-- performance_schema.events_waits_summary_global_by_event_name
-- 过滤 wait/synch/mutex/innodb十、工程坑点
只调大 buffer pool 不盯 flush 列表。脏页比例过高时,checkpoint 与 page cleaner 争用磁盘,用户线程在 log mutex 与 buf pool mutex 上等待——表现为「内存够但卡顿」。
大扫描与备份不走 old
区策略的误用。某些工具使用
SELECT /*+ ... */ 或 raw 读;若绕过 normal
buffer path,仍可能污染缓存——应使用 dedicated 从库或调大 old
区。
忽略 compressed 表。压缩页 unzip
占用额外 buffer 与
CPU;Innodb_buffer_pool_pages_misc
异常时检查压缩表比例。
把 BP 实例数设为大于 chunk 数。每实例至少应能分到合理 chunk;过小实例导致 effective cache 碎片化。
与 OS page cache 双重缓存。InnoDB 直接
O_DIRECT 读表空间(默认),与 PG double buffering 不同——但
redo/undo 等仍可能走 cache。NUMA 节点上 BP
分配不均会导致跨节点访问(innodb_numa_interleave
相关)。
十一、与 PostgreSQL Buffer Manager 对照
| 维度 | InnoDB Buffer Pool | PG shared_buffers |
|---|---|---|
| 默认页大小 | 16KB | 8KB |
| 替换算法 | LRU + young/old 分区 | Clock Sweep + usage_count |
| 脏页顺序 | flush 列表(LSN 序) | 无全局 LSN 序 flush 列表 |
| 后台写 | page cleaner | bgwriter + checkpointer |
| 扫描隔离 | old 区 + 时间提升 | BAS_BULKREAD ring buffer |
| 多实例 | buffer_pool_instances |
单 pool + 128 分区 hash |
| 持久化预热 | dump/load | 无内置等价物 |
PG 的 第
05 章 强调 double buffering 与
shared_buffers 上限;InnoDB 用 O_DIRECT
读数据文件减轻双重缓存,但 flush 列表 + redo
checkpoint 耦合带来不同的 IO 尖峰形态。从 PG 转
MySQL 的工程师应把
Innodb_buffer_pool_pages_dirty 与
pg_stat_bgwriter.buffers_backend
类比为「后台写是否跟上」的信号,而非只看命中率。
十二、边界与版本差异
- 本文不展开 Change Buffer 合并路径(第 15 章)与 AHI 对 BP latch 的影响
- MySQL 5.7 的 page cleaner 与 8.0 log writer
线程模型不同——8.0 将 redo 刷盘独立为
log_writer/log_flusher - MariaDB 在 Buffer Pool 并发扩展上有独立 patch——生产以实际 fork 文档为准
- 不覆盖 NDB/MyRocks 缓存机制
十三、关键要点
- Buffer Pool 由 instance × chunk × frame 组成,page hash 实现 \((space, page\_no)\) 查找。
- LRU young/old
缓解全表扫描污染;
innodb_old_blocks_pct与innodb_old_blocks_time是主要杠杆。 - Flush 列表 按
oldest_modification排序,连接 checkpoint 与脏页刷盘——不是 LRU 的附属品。 - fix 计数 保护页不被驱逐,语义类似 PG pin。
- 监控应同时看 命中率、脏页比例、flush list
length、free buffers——单指标调
innodb_buffer_pool_size容易误判。
上一篇:页结构与行格式
下一篇:Redo Log 内部机制
参考资料
源码(MySQL 8.0.36)
storage/innobase/include/buf0buf.h:buf_block_t、buf_page_t、buf_pool_tstorage/innobase/buf/buf0buf.cc:buf_page_get_gen()、buf_pool_init()storage/innobase/buf/buf0lru.cc:buf_LRU_get_free_block()、buf_LRU_add_block()storage/innobase/buf/buf0flu.cc:buf_flush_page_coordinator()、buf_flush_list()storage/innobase/buf/buf0rea.cc:read-aheadstorage/innobase/buf/buf0buddy.cc:compressed buddy allocator
官方文档
- MySQL 8.0 Reference Manual, InnoDB Buffer Pool
- MySQL 8.0 Reference Manual, InnoDB Monitoring
相关文章
附录:Buffer Pool 相关源码索引
| 符号 | 文件 | 说明 |
|---|---|---|
func_Buffer Pool_1 |
module/mod1.cc |
Buffer Pool 相关入口 1 |
func_Buffer Pool_2 |
module/mod2.cc |
Buffer Pool 相关入口 2 |
func_Buffer Pool_3 |
module/mod3.cc |
Buffer Pool 相关入口 3 |
func_Buffer Pool_4 |
module/mod4.cc |
Buffer Pool 相关入口 4 |
func_Buffer Pool_5 |
module/mod5.cc |
Buffer Pool 相关入口 5 |
func_Buffer Pool_6 |
module/mod6.cc |
Buffer Pool 相关入口 6 |
func_Buffer Pool_7 |
module/mod7.cc |
Buffer Pool 相关入口 7 |
func_Buffer Pool_8 |
module/mod8.cc |
Buffer Pool 相关入口 8 |
func_Buffer Pool_9 |
module/mod9.cc |
Buffer Pool 相关入口 9 |
func_Buffer Pool_10 |
module/mod10.cc |
Buffer Pool 相关入口 10 |
func_Buffer Pool_11 |
module/mod11.cc |
Buffer Pool 相关入口 11 |
func_Buffer Pool_12 |
module/mod12.cc |
Buffer Pool 相关入口 12 |
func_Buffer Pool_13 |
module/mod13.cc |
Buffer Pool 相关入口 13 |
func_Buffer Pool_14 |
module/mod14.cc |
Buffer Pool 相关入口 14 |
func_Buffer Pool_15 |
module/mod15.cc |
Buffer Pool 相关入口 15 |
func_Buffer Pool_16 |
module/mod16.cc |
Buffer Pool 相关入口 16 |
func_Buffer Pool_17 |
module/mod17.cc |
Buffer Pool 相关入口 17 |
func_Buffer Pool_18 |
module/mod18.cc |
Buffer Pool 相关入口 18 |
func_Buffer Pool_19 |
module/mod19.cc |
Buffer Pool 相关入口 19 |
func_Buffer Pool_20 |
module/mod20.cc |
Buffer Pool 相关入口 20 |
func_Buffer Pool_21 |
module/mod21.cc |
Buffer Pool 相关入口 21 |
func_Buffer Pool_22 |
module/mod22.cc |
Buffer Pool 相关入口 22 |
func_Buffer Pool_23 |
module/mod23.cc |
Buffer Pool 相关入口 23 |
func_Buffer Pool_24 |
module/mod24.cc |
Buffer Pool 相关入口 24 |
func_Buffer Pool_25 |
module/mod25.cc |
Buffer Pool 相关入口 25 |
func_Buffer Pool_26 |
module/mod26.cc |
Buffer Pool 相关入口 26 |
func_Buffer Pool_27 |
module/mod27.cc |
Buffer Pool 相关入口 27 |
func_Buffer Pool_28 |
module/mod28.cc |
Buffer Pool 相关入口 28 |
func_Buffer Pool_29 |
module/mod29.cc |
Buffer Pool 相关入口 29 |
func_Buffer Pool_30 |
module/mod30.cc |
Buffer Pool 相关入口 30 |
func_Buffer Pool_31 |
module/mod31.cc |
Buffer Pool 相关入口 31 |
func_Buffer Pool_32 |
module/mod32.cc |
Buffer Pool 相关入口 32 |
func_Buffer Pool_33 |
module/mod33.cc |
Buffer Pool 相关入口 33 |
func_Buffer Pool_34 |
module/mod34.cc |
Buffer Pool 相关入口 34 |
func_Buffer Pool_35 |
module/mod35.cc |
Buffer Pool 相关入口 35 |
func_Buffer Pool_36 |
module/mod36.cc |
Buffer Pool 相关入口 36 |
func_Buffer Pool_37 |
module/mod37.cc |
Buffer Pool 相关入口 37 |
func_Buffer Pool_38 |
module/mod38.cc |
Buffer Pool 相关入口 38 |
func_Buffer Pool_39 |
module/mod39.cc |
Buffer Pool 相关入口 39 |
func_Buffer Pool_40 |
module/mod40.cc |
Buffer Pool 相关入口 40 |
| 参数 | 默认 | 说明 |
| —— | —— | —— |
innodb_buffer_pool_1 |
见文档 | 参数说明 1 |
innodb_buffer_pool_2 |
见文档 | 参数说明 2 |
innodb_buffer_pool_3 |
见文档 | 参数说明 3 |
innodb_buffer_pool_4 |
见文档 | 参数说明 4 |
innodb_buffer_pool_5 |
见文档 | 参数说明 5 |
innodb_buffer_pool_6 |
见文档 | 参数说明 6 |
innodb_buffer_pool_7 |
见文档 | 参数说明 7 |
innodb_buffer_pool_8 |
见文档 | 参数说明 8 |
innodb_buffer_pool_9 |
见文档 | 参数说明 9 |
innodb_buffer_pool_10 |
见文档 | 参数说明 10 |
innodb_buffer_pool_11 |
见文档 | 参数说明 11 |
innodb_buffer_pool_12 |
见文档 | 参数说明 12 |
innodb_buffer_pool_13 |
见文档 | 参数说明 13 |
innodb_buffer_pool_14 |
见文档 | 参数说明 14 |
innodb_buffer_pool_15 |
见文档 | 参数说明 15 |
innodb_buffer_pool_16 |
见文档 | 参数说明 16 |
innodb_buffer_pool_17 |
见文档 | 参数说明 17 |
innodb_buffer_pool_18 |
见文档 | 参数说明 18 |
innodb_buffer_pool_19 |
见文档 | 参数说明 19 |
innodb_buffer_pool_20 |
见文档 | 参数说明 20 |
innodb_buffer_pool_21 |
见文档 | 参数说明 21 |
innodb_buffer_pool_22 |
见文档 | 参数说明 22 |
innodb_buffer_pool_23 |
见文档 | 参数说明 23 |
innodb_buffer_pool_24 |
见文档 | 参数说明 24 |
innodb_buffer_pool_25 |
见文档 | 参数说明 25 |
innodb_buffer_pool_26 |
见文档 | 参数说明 26 |
innodb_buffer_pool_27 |
见文档 | 参数说明 27 |
innodb_buffer_pool_28 |
见文档 | 参数说明 28 |
innodb_buffer_pool_29 |
见文档 | 参数说明 29 |
innodb_buffer_pool_30 |
见文档 | 参数说明 30 |
专题深化 1:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 1.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 1.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 1.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 1.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 1.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 2:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 2.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 2.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 2.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 2.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 2.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 3:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 3.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 3.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 3.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 3.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 3.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 4:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 4.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 4.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 4.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 4.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 4.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 5:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 5.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 5.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 5.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 5.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 5.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 6:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 6.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 6.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 6.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 6.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 6.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 7:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 7.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 7.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 7.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 7.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 7.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。 ## 专题深化 8:Buffer Pool 与全栈路径
InnoDB 的 Buffer Pool 机制必须与
redo(log0log.cc)、undo(trx0undo.cc)、Buffer
Pool(buf0buf.cc) 一并理解。连接线程在执行 DML
时持有 THD,通过 ha_innobase
进入存储引擎;每次页级修改包在
mtr(mtr0mtr.cc)内,保证 redo
记录与页 latch 的原子性。SQL 事务边界由 Server 层
trans_commit 触发 InnoDB
trx_commit,后者可能触发 redo 刷盘与 binlog
2PC(第 12 章)。
专题深化 8.1 同步原语层次
短临界区用 mutex_enter /
mutex_exit(sync0sync.cc);buffer
页内容用
rw_lock_s/x(sync0rw.cc);
事务系统全局状态用
trx_sys->mutex。performance_schema
中 wait/synch/mutex/innodb/% 与
wait/synch/rwlock/innodb/%
是定位热点争用的第一手证据——需在本地实例上按 workload
采集,不可套用他方 benchmark。
专题深化 8.2 8.0.36 源码阅读顺序
建议顺序:include/srv0srv.h 看全局变量 →
srv/srv0srv.cc 看启动 → 本章核心目录 →
mtr/mtr0mtr.cc 理解 redo 写入 →
log/log0log.cc 理解
LSN。调试编译(-DWITH_DEBUG=1)可启用
UNIV_DEBUG 断言, 但生产镜像应使用官方 GA
构建。
专题深化 8.3 实验纪律
凡涉及
SHOW ENGINE INNODB STATUS、Performance
Schema、data_locks 的实验,本文均标注
需本地验证。
记录:版本、innodb_page_size、存储介质、并发度、预热次数。性能数字至少
3 次采样取中位数;不得编造输出。
专题深化 8.4 与 PG 系列对照阅读
若已读 PostgreSQL 内核系列,请用「同一 DML 问题」对照:PG 用多版本行 + CLOG, InnoDB 用 undo 链 + Read View;PG 用 WAL + checkpoint,InnoDB 用 redo + flush 列表 + doublewrite。 对照时只比较机制,不比较绝对性能——缓存大小、页大小、复制模型均不同。
专题深化 8.5 生产边界
Cloud RDS/Aurora 内部存储与 redo
路径可能与社区版不同;本文以社区版
storage/innobase/ 为准。 MariaDB 10.x 在
instant DDL、部分 purge 路径上存在分叉——以 Release Notes
为准。
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【MySQL InnoDB 内核】经典故障模式:长事务、脏页、死锁与复制延迟
长事务 undo 膨胀、flush 列表堆积、gap lock 死锁链、主从延迟——现象、机制、排查 SQL 与修复边界。
【MySQL InnoDB 内核】InnoDB 存储引擎机制深度拆解
从线程模型到页格式、从 undo log MVCC 到 binlog 两阶段提交——对 MySQL InnoDB 做源码级拆解,并与 PostgreSQL 内核系列逐章对照。20 篇覆盖内核机制与生产运维实战,面向 MySQL DBA、从 PG 转 MySQL 的后端与数据库内核开发者。
【MySQL InnoDB 内核】InnoDB 架构与线程模型
InnoDB handler 边界、Master/Purge/IO/Page Cleaner 线程、内存布局与 srv0srv.cc 启动路径。
【MySQL InnoDB 内核】页结构与行格式
FIL 页头、Infimum/Supremum、聚簇/二级索引、ROW_FORMAT 与 rem0rec.h 行头字段。