MySQL 8.0Notes

第 16 章:Buffer Pool

zjc 于 2026-01-16 发布

这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Buffer Pool 是 InnoDB 的内存页缓存。脏页、干净页、索引页、undo 页、锁信息和 AHI 都与其生命周期相关。

16.1 基本结构

logical page request
  -> page hash lookup
     |-- hit: return block
     +-- miss:
        -> read page from disk
           -> insert into LRU
              -> return block

关键点:

  1. 以页为单位缓存;
  2. 查找通过 page hash;
  3. 淘汰通过 LRU 变体;
  4. 修改页成为脏页;
  5. 脏页由 page cleaner 刷盘;
  6. 页 latch 控制并发访问。

16.2 LRU 变体

InnoDB 使用 young/old 子链表,降低全表扫描污染热数据的风险。

new pages
  -> old sublist
     -> survive threshold time
        -> move to young sublist

相关参数:

参数 说明
innodb_buffer_pool_size 总大小
innodb_buffer_pool_instances 实例数
innodb_old_blocks_pct old 区比例
innodb_old_blocks_time 进入 young 的停留时间

16.3 脏页刷盘

modify page in memory
  -> mark dirty
     -> write redo first
     -> page cleaner flush
        -> doublewrite
           -> data file

触发条件:

  1. redo 空间压力;
  2. 脏页比例;
  3. LRU 空间不足;
  4. checkpoint;
  5. shutdown;
  6. 用户线程辅助。

相关参数:

参数 说明
innodb_max_dirty_pages_pct 脏页比例目标
innodb_io_capacity 正常刷盘能力
innodb_io_capacity_max 压力上限
innodb_lru_scan_depth LRU 扫描深度

16.4 命中率

SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';

常用计算:

hit rate = 1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
现象 方向
命中率低 内存不足、随机 IO、冷数据、大扫描
命中率高但慢 CPU、锁、日志、网络
脏页高 刷盘能力不足
free wait LRU 空间紧张

16.5 并发控制

Buffer Pool 并发涉及:

  1. buffer pool instance mutex;
  2. page latch;
  3. LRU list mutex;
  4. flush list mutex;
  5. free list mutex;
  6. AHI latch。

性能视图:

SELECT event_name, count_star, sum_timer_wait
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE event_name LIKE 'wait/synch/mutex/innodb/%'
ORDER BY sum_timer_wait DESC;

16.6 在线调整

SET GLOBAL innodb_buffer_pool_size=8589934592;

在线调整可能引发内存分配和内部锁等待,应在低峰执行并监控状态:

SHOW STATUS LIKE 'Innodb_buffer_pool_resize_status';

生产建议提前规划内存,不把它当常规动态调优手段。

16.7 页面观测

SELECT SPACE, PAGE_TYPE, COUNT(*) AS pages
FROM information_schema.innodb_buffer_page
GROUP BY SPACE, PAGE_TYPE
ORDER BY pages DESC
LIMIT 20;

查询系统表可能产生额外开销,生产上应限流或在测试库分析。

16.8 源码入口

文件 内容
buf0buf.cc Buffer Pool 核心
buf0lru.cc LRU 和淘汰
buf0flu.cc 刷脏
buf0rea.cc 预读
buf0dblwr.cc doublewrite

断点:

b buf_page_get_gen
b buf_LRU_get_free_block
b buf_flush_page

本章小结

Buffer Pool 通过 LRU 变体缓存页,通过脏页列表和 page cleaner 异步落盘。命中率和脏页趋势是内存与 IO 判断的核心指标,在线调大需谨慎。

思考题

  1. 为什么 InnoDB LRU 分 young/old 区?
  2. redo log 压力如何影响脏页刷盘?
  3. 命中率低有哪些原因?
  4. dirty pages 高说明什么?
  5. 在线调整 Buffer Pool 应注意什么?