土法炼钢兴趣小组的算法知识备份

【MySQL InnoDB 内核】Buffer Pool 与 LRU:frame、flush 列表与 young/old 分区

文章导航

分类入口
databasekernel
标签入口
#mysql#innodb#buffer-pool#lru#flush-list#buf0buf

目录

Buffer Pool 与 LRU:frame、flush 列表与 young/old 分区

innodb_buffer_pool_size 调到物理内存的 80%,TPS 反而下降——SHOW ENGINE INNODB STATUSBuffer pool hit rate 仍然很高,但 checkpoint 期间 pending flush 暴涨,业务线程在 log flushbuf 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.36storage/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 的衔接

页在内存中被修改时:

  1. Mini-Transaction(mtr) 把字节级变更写入 redo log buffer(第 4 章)
  2. 页的 oldest_modificationflush 列表 关联——决定 checkpoint 能推进到哪里
  3. 脏页落盘前经 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.ccbuf_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_tbuf_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):


三、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 分为:

首次读入的页进入 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.ccbuf_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 可缓解。

配置:

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_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_dirtypg_stat_bgwriter.buffers_backend 类比为「后台写是否跟上」的信号,而非只看命中率。


十二、边界与版本差异


十三、关键要点

  1. Buffer Pool 由 instance × chunk × frame 组成,page hash 实现 \((space, page\_no)\) 查找。
  2. LRU young/old 缓解全表扫描污染;innodb_old_blocks_pctinnodb_old_blocks_time 是主要杠杆。
  3. Flush 列表oldest_modification 排序,连接 checkpoint 与脏页刷盘——不是 LRU 的附属品。
  4. fix 计数 保护页不被驱逐,语义类似 PG pin。
  5. 监控应同时看 命中率、脏页比例、flush list length、free buffers——单指标调 innodb_buffer_pool_size 容易误判。

上一篇页结构与行格式

下一篇Redo Log 内部机制

参考资料

源码(MySQL 8.0.36)

官方文档

相关文章

附录: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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 1.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 2.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 3.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 4.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 5.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 6.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 7.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 进入存储引擎;每次页级修改包在 mtrmtr0mtr.cc)内,保证 redo 记录与页 latch 的原子性。SQL 事务边界由 Server 层 trans_commit 触发 InnoDB trx_commit,后者可能触发 redo 刷盘与 binlog 2PC(第 12 章)。

专题深化 8.1 同步原语层次

短临界区用 mutex_enter / mutex_exitsync0sync.cc);buffer 页内容用 rw_lock_s/xsync0rw.cc); 事务系统全局状态用 trx_sys->mutexperformance_schemawait/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 为准。

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-18 · database / kernel

【MySQL InnoDB 内核】InnoDB 存储引擎机制深度拆解

从线程模型到页格式、从 undo log MVCC 到 binlog 两阶段提交——对 MySQL InnoDB 做源码级拆解,并与 PostgreSQL 内核系列逐章对照。20 篇覆盖内核机制与生产运维实战,面向 MySQL DBA、从 PG 转 MySQL 的后端与数据库内核开发者。


By .