buffer pool是innodb以16kb页为单位缓存数据与索引的核心内存区域,通过free、lru、flush三大链表分工管理空闲页、热数据页和脏页,并采用分代lru策略防污染,确保热数据常驻、冷数据及时释放、脏数据安全落盘。

MySQL InnoDB 的 Buffer Pool 通过内存页管理、链表组织和分代淘汰三重机制协同管理数据页,核心目标是让热数据常驻内存、冷数据及时释放、脏数据安全落盘。
页是唯一操作单位
InnoDB 不按行也不按字段操作,而是以固定大小的数据页(默认16KB)为最小单位加载、缓存和刷写。哪怕只查一条记录,也会把整页从磁盘读入 Buffer Pool;后续对该页内其他记录的访问,全部在内存中完成,彻底避免重复磁盘 I/O。
- 一个页可能包含多行数据、索引项、undo 日志片段或插入缓存条目
- 每个页在 Buffer Pool 中都配有一个控制块(buf_block_t),记录空间 ID、页号、LSN、锁信息等元数据
- 控制块本身不计入
innodb_buffer_pool_size配置值,实际内存占用约比配置值高 5%
三大链表分工协作
Buffer Pool 内部用三个双向链表对页进行分类管理,互不干扰又彼此关联:
- Free List(空闲链表):存放尚未使用的空白页。新页加载时优先从此链表分配;页被使用后立即移出
-
LRU List(最近最少使用链表):管理所有已加载页(含 clean 和 dirty 页),按访问热度排序。它被逻辑分为 New 区(前 63%)和 Old 区(后 37%),由
innodb_old_blocks_pct控制比例 - Flush List(刷新链表):仅包含被修改过的脏页(dirty page),按修改时间(LSN)升序排列,便于后台线程批量刷盘
注意:一个脏页会同时存在于 LRU List 和 Flush List 中——前者管“要不要留”,后者管“什么时候写”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
分代 LRU 淘汰策略防污染
为避免全表扫描或预读导致热数据被挤出,InnoDB 放弃传统 LRU,采用Midpoint Insertion 策略:
- 新加载的页不直接插到 LRU 头部,而是先放入 Old 区头部
- 若该页在
innodb_old_blocks_time(默认 1000ms)内被再次访问,才提升到 New 区头部 - 未被二次访问的页,在 Old 区逐步沉底,最终被淘汰
- 预读页(如线性预读触发的 64 页)也走此路径,1 秒不热即丢,不冲击热区
后台线程保障数据一致性
Buffer Pool 不是静态缓存,而由多个后台线程持续维护:
-
Page Cleaner:定期扫描 Flush List,将最旧的脏页刷回磁盘,控制脏页比例(
innodb_max_dirty_pages_pct) -
Buffer Pool Dump/Load:支持实例重启后快速恢复热点页(
innodb_buffer_pool_dump_at_shutdown) -
Multiple Instances:当
innodb_buffer_pool_size > 1GB时自动拆分为多个 instance(数量由innodb_buffer_pool_instances控制),减少并发访问锁竞争
这种设计让 Buffer Pool 在高并发读写下仍能保持低延迟与高命中率,是 InnoDB 性能的底层支柱。










