深入浅出 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链表中)。

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

相关推荐
Yuzhiyuxia3 分钟前
【AI Agent面试系列】AI Agent可观测、评测、安全相关的知识点
人工智能·安全·面试
我不会起名字32236 分钟前
seq 空洞排查:Mongo 的 51 只是预留上界,Redis CURR 才是已消耗边界
redis·后端·mongodb·go·即时通讯·im·故障排查
特立独行的猫A36 分钟前
少 3 个环节、少 1 次 ABI、少 3500 行代码:cj-tauri 与 Ionic/Capacitor 的鸿蒙桥接机制对比
java·后端·python
学长毕设1 小时前
基于SpringBoot的高校后勤报修管理系统-附源码
java·spring boot·后端
特立独行的猫A1 小时前
cj-tauri vs Rust/Tauri 同款播放器实测:编译 21 秒 vs 11 分钟,磁盘 12 MB vs 1.2 GB
java·后端·python
乐橙开放平台1 小时前
海康和大华摄像头能统一管理吗?可以通过 GB28181 或视频融合平台接入
网络·后端·物联网·音视频
时间的拾荒人4 小时前
Redis 集合类型详解:Set 与 Zset
redis·缓存·面试
一条Go5 小时前
OnCall 时段路由:跨午夜、左闭右开与「Local 不是时区」
后端·架构·github
Moment5 小时前
不会后期的我,发现了一个开源胶片神器😍😍😍
前端·后端·开源
数据库小学妹5 小时前
pgbouncer 事务池:prepared statement、临时表与会话状态
数据库·后端·postgresql