innoDB的buffer pool

发布于:2025-08-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

innoDB

分为内存结构和磁盘结构两个部分,其中内存结构的主要部分是buffer pool。

buffer pool

innoDB的内存架构的主要部分

本质与作用

buffer pool是innoDB引擎内的一个重要组件,是一个内存缓存,它的性能直接影响到innoDB的表现。通过缓存数据和索引,将磁盘 I/O 转化为内存操作,使 CRUD 操作从 毫秒级(磁盘) 降至 微秒级(内存)。合理配置 Buffer Pool 大小、实例数和刷盘策略,是优化 MySQL 性能的关键步骤。

作用:缓存磁盘上的表数据页(data page)和索引页(index page),减少磁盘 I/O。

读的大概流程:查询到某个buffer pool实例,使用哈希算法找到要查取的数据,查取,然后返回,如果没查到,去磁盘查,读到buffer pool中。 写的大概流程:先把数据和日志写入 buffer pool 和 log buffer,再由后台线程以一定频率将 buffer 中的内容刷到磁盘,「这个刷盘机制叫做Checkpoint」

大致的查询流程如下:[1]

内部结构

Buffer Pool的本质就是一大块内存数据结构,由多个缓存页和其控制块组成,另外配套的各种链表数据结构(free、flush、LRU)来辅助执行引擎的运行。

结构:

Buffer Pool 通过 数据页(缓存页) + 控制块 的组合存储数据,利用 Free/LRU/Flush 链表 管理页的生命周期,结合 哈希表 加速访问,并通过 多实例与 Chunk 优化高并发场景。其设计核心是平衡内存利用率、访问效率和数据一致性,是 InnoDB 实现高性能的关键。

存储数据

由 缓存页+控制块 构成,数据存在缓存页中,控制块存这个缓存页的元信息[2]。 在Buffer Pool中,每个缓存页的控制块放在最前面,然后各个缓存页放在后面,大概如下图所示:[3],[4]

Buffer Pool默认大小 128M,用于缓存数据页(16KB),控制块大小约800个字节(不到1KB)。所以配置 innodb_buffer_pool_size=128M 时,InnoDB 实际会申请约 134MB 内存(多出的 6MB 用于控制块)。

free链表

当需要加载新的缓存页时,执行引擎是如何知道哪些缓存页是空闲的呢?

答案是使用free链表对空白缓存页进行管理,在Buffer Pool中会有一个双向链表数据结构的free链表。在这个链表中存储的每个节点是一个空闲缓存页的控制块的地址。只要存在一个缓存页是空闲的,此时对应的控制块就会被放入这个free链表中。

flush链表

如果一个缓存页被写了,那么这页就成为脏页,flush链表就是记录脏页的。其原理和free链表一样,只不过存的是脏页而不是空白页。

LRU链表

成熟的缓存都有这个机制,不然只进数据不出数据,是不现实的。 这里的lru链表和其他的lru链表也没什么不同,都是只要被查取了,就放到前面去,淘汰就拿最后的。

冷热分离策略

MySQL会预读多一些的数据,多出来的数据,不能算是热点数据,如果放到链表前面,把后面的真热点数据挤出去了,是很不好的事情。这里lru会采用冷热分离的策略,大致思路就是把真热点数据放到前面,预读来的非热点的数据放到后面。冷热数据的比例是由参数innodb_old_blocks_pct参数控制的,默认配置为37,代表了冷数据占比37%

简答:

  • 将 LRU 链表分为两部分:

    • new 区(热数据区):占 63%

    • old 区(冷数据区):占 37%

  • 新数据从 midpoint(冷数据区头部)插入

  • 数据页在 old 区停留时间超过 innodb_old_blocks_time(默认 1s)后,再次访问才会移到 new 区19

哈希表

MySQL如何知道一个数据页是否被缓存?答案是使用哈希表。 这个哈希表的key采用表空间号和数据页号组成,value存储缓存页地址。

脏页-刷盘持久化

通过对上述三种链表的描述,我们知道「当我们对数据进行修改时,其实修改的是Buffer Pool 中数据所在缓存页,修改后将其设置为脏页,并将脏页的控制块同时存在于 LRU 链表和 Flush 链表」。然后通过刷脏将修改同步至磁盘[5]。

刷脏不是每次修改都进行的,那样性能会很差,因此刷脏是通过一定的时机触发进行批量刷盘的。

脏页的刷盘时机总的来说就分为以下种:

  • redo log 日志满了的情况下,会主动触发脏页刷新到磁盘;

  • MySQL 正常关闭之前,会把所有的脏页刷入到磁盘;

  • Buffer Pool 空间不足时,会淘汰一部分数据页,如果淘汰的是脏页,需要先将其同步到磁盘。

  • MySQL 空闲时,后台线程会定期脏页刷盘

--

注释&引用

[1]MySQL缓冲池(buffer pool),这次终于懂了_mysql bufferpool-CSDN博客
[2]缓存页原信息指的是当前缓存页所对应的表空间数据页编号、当前缓存页在Buffer Pool中的地址信息等。
[3]所有相似风格的图中所有《描述数据》都为文中的《控制块》
[4]04.MySQL InnoDB Buffer Pool深度解析 - 《MySQL》 - 极客文档
[5]MySQL十六:36张图理解Buffer Pool - 云扬四海 - 博客园


网站公告

今日签到

点亮在社区的每一天
去签到