深入浅出 MySQL Buffer Pool

前言

本篇文章主要讲解了 MySQL Buffer Pool,来看看在高并发下 MySQL Buffer Pool 到底是如何工作的。

什么是 Buffer Pool?

学过计算机组成原理的同学们都知道,我们想要取出硬盘(固态硬盘 / 机械硬盘)中的数据是消耗非常大的,如果是想取出内存(运行内存)中的数据消耗,相比较于硬盘那就小得多了。

在 MySQL 的 InnoDB 存储引擎中,所有数据都存储在磁盘上,但其管理的最小逻辑单位是 数据页(Data Page) ,每一页内部包含了多行数据记录。为了减少昂贵的磁盘 I/O 操作,InnoDB 引入了核心的内存组件------缓冲池(Buffer Pool)

当客户端发起读请求时,InnoDB 会首先在 Buffer Pool 中查找所需的数据页。如果数据页已存在于缓冲池中(即缓存命中 ),则会直接从内存中读取并返回,速度极快。如果不存在(即缓存未命中),InnoDB 则会先从磁盘将该数据页加载到 Buffer Pool 中,然后再从内存中读取返回。

Free 链表

我们知道,Buffer Pool 就像一个为了加速数据读取而设置的"内存旅馆"。当 MySQL 刚启动时,这个"旅馆"里所有的"房间"(缓冲页)都是空的。那么,如何快速找到一间空房并登记入住呢?

这就是 Free 链表 的工作了。你可以把它想象成旅馆前台的一个**"空房列表"**。这个列表是一个双向链表,串联起了所有可用的空房间。

当需要为新的数据页(新客人)分配空间时,InnoDB 不需要逐个房间去检查,而是直接查看"空房列表"的第一个记录,立即就能找到一个空房间。一旦这个房间被分配,它就会从"空房列表"(Free 链表)中移除。

流程如下:

  • 从 Free 链表的头部获取一个节点,该节点指向一个空闲的缓冲页。
  • 将数据加载到该缓冲页中,并更新其元数据信息。
  • 最后,将该节点从 Free 链表 中移除,并将其加入到 LRU 链表中,以便进行后续的访问和淘汰管理。

LRU 链表

LRU (Least Recently Used) 是一种经典的缓存淘汰算法,其核心思想是"末位淘汰"。您可以将 LRU 链表想象成一个活跃数据排行榜

当一个数据页被访问时,它会被提升到排行榜的头部 (Head) ,代表它是最近被使用的"热点数据"。而长期没有被访问的数据页,则会逐渐沉降到链表的尾部 (Tail)。当 Buffer Pool 空间不足,需要释放空间时,就会优先从链表尾部淘汰那些最久未被使用的"冷数据"。

InnoDB 在此基础上做了优化 :新加载的数据页并不会 立即被放到链表的最头部,而是放在一个中间位置。只有当这个页在"年轻"的状态下被再次访问时,才会被真正移动到最头部,成为名副其实的热点数据。这个小小的改动,极大地提高了 Buffer Pool 在应对全表扫描等操作时的稳定性。

Flush 链表

Flush 链表与 Free 链表结构类似,也是一个双向链表。但其核心作用并非删除脏页 ,而是追踪并管理所有在内存中被修改过、但尚未同步到磁盘的缓冲页(即"脏页")

脏页的产生源于写操作(INSERT, UPDATE, DELETE)。为了提升性能,InnoDB 会先更新内存中的缓冲页,并立即将变更写入 redo log 。此时,内存页的数据就领先于磁盘页,该缓冲页的控制块便会被加入到 Flush 链表中,标记其为"脏页"。

InnoDB 的后台线程(如 Page Cleaner Threads)会定期遍历 Flush 链表,将这些脏页异步地、分批地写回磁盘。这个过程称为**"刷脏" (Flushing)**。一旦刷脏完成,该页就变为"干净页",并会从 Flush 链表中移除(但它依然存在于LRU链表中)。

这种机制实现了写操作的延迟和异步化,用户请求无需等待缓慢的磁盘写入即可返回,极大地提高了数据库的写入性能和吞吐量。

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
晨米酱2 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
大勇前进2 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu2 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile2 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白802 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙2 天前
PHP 接口返回统一响应封装,让前后端对接更省心
后端