MySQL Buffer Pool深度解析:当缓存页不足时如何基于LRU算法进行淘汰

1. 问题引入:free链表空了怎么办?

在之前的文章中,我们详细讲解了MySQL Buffer Pool中缓存页的划分、free链表的管理,以及数据页从磁盘加载到缓存页的过程。今天我们来分析一个更实际的问题:当Buffer Pool中的空闲缓存页用完时,系统该如何处理?

1.1 缓存页耗尽的必然性

随着数据库持续运行,不断有数据页从磁盘加载到Buffer Pool中:

  • 每次数据加载都会从free链表获取一个空闲缓存页
  • free链表中的节点会越来越少
  • 最终必然出现free链表为空的情况
markdown 复制代码
磁盘数据页 → 查找free链表 → 获取空闲缓存页 → 加载数据

当free链表耗尽时,新的数据页将无法加载,此时必须淘汰部分现有缓存页

2. 淘汰策略:该把谁"请"出内存?

2.1 什么是淘汰缓存页?

淘汰缓存页是指:

  1. 将被修改过的缓存页数据刷新到磁盘(如果它是脏页)
  2. 清空该缓存页
  3. 将其重新加入free链表,变为可用状态

这个过程确保了内存资源的循环利用,但引出一个关键问题:应该淘汰哪些缓存页?

3. 核心指标:缓存命中率

为了做出最优淘汰决策,MySQL引入了缓存命中率的概念:

场景 访问频率 命中率评估 淘汰优先级
缓存页A 100次请求中30次访问 高命中率 保留
缓存页B 加载后仅访问1次,后续100次请求无访问 低命中率 优先淘汰

核心原则:优先淘汰"占着茅坑不拉屎"的缓存页------即那些长期不被访问却占用内存资源的页面。

4. LRU链表:智能淘汰的指挥官

4.1 LRU基本概念

MySQL通过LRU链表(Least Recently Used,最近最少使用)来实现智能淘汰:

工作原理:最近被访问的缓存页移动到链表头部,久未访问的页面自然沉降到尾部。

4.2 LRU链表运作机制

数据加载时

当从磁盘加载数据页到缓存页:

  • 将该缓存页的描述信息块放入LRU链表头部
  • 表示这是最新被使用的页面
markdown 复制代码
[新加载的缓存页] → LRU Head → ... → LRU Tail
数据访问时

当查询或修改某个已存在的缓存页:

  • 无论该缓存页在LRU链表的哪个位置
  • 立即将其移动到链表头部
  • 表示它刚被访问过,近期可能再次被访问
markdown 复制代码
LRU Tail中的缓存页被访问 → 移动到LRU Head
淘汰决策时

当需要腾出空闲缓存页:

  • 直接从LRU链表尾部选取
  • 尾部的页面就是"最近最少使用"的页面
  • 将其刷新到磁盘后清空

5. 技术图解

图1:free链表耗尽的场景

复制代码
Buffer Pool (128MB)
┌─────────────────────────────────────┐
│ [数据] [数据] [数据] ... [数据]          │
│ 缓存页  缓存页  缓存页      缓存页      │
└─────────────────────────────────────┘
        ▲
        │ 无法加载新数据页
        │
磁盘文件 ────────────→ X (无空闲缓存页)

图2:LRU链表驱动的淘汰流程

复制代码
1. 识别LRU链表尾部页面(最少使用)
   ↓
2. 如果是脏页,刷新到磁盘
   ↓
3. 清空缓存页,加入free链表
   ↓
4. 加载新数据页到腾出的空间
   ↓
5. 新页面插入LRU链表头部

6. 思考题解答:表/行 vs 表空间/数据页

问题:SQL中的表、行与表空间、数据页之间是什么关系?

答案

  • 逻辑概念:表、列、行------面向开发者的抽象,关注数据结构
  • 物理概念:表空间、数据页------面向存储的实现,关注数据在磁盘的组织方式

类比

就像你看一本书,只关注"章节"和"段落"(逻辑),而不必关心"纸张"和"印刷墨迹"(物理)。数据库自动将逻辑结构映射为物理存储。

7. 总结要点

  1. free链表耗尽是常态:持续的数据加载必然导致空闲页用完
  2. LRU是淘汰依据:通过访问时间戳智能判断页面热度
  3. 头部-尾部机制:热点数据在头部,冷数据自然沉降尾部
  4. 性能保障:确保内存中保留的都是高价值数据,最大化缓存命中率

系列预告:下一篇文章将深入探讨MySQL LRU算法的优化细节,包括如何解决"全表扫描污染缓存"等经典问题。

参考资料:《MySQL专栏》

版权说明:本文内容整理自狸猫技术窝MySQL专栏,仅供学习交流使用。

相关推荐
万物得其道者成12 分钟前
用 Python + MySQL + Web 打造我的私有 Apple 设备监控面板
前端·python·mysql
kaico201824 分钟前
MYSQL的日志文件
数据库·mysql
我的golang之路果然有问题2 小时前
mysql 个人笔记导出之-数据库时间戳问题以及增删改查
数据库·笔记·学习·mysql·分享·个人笔记
JH30732 小时前
我的笔记:怎么用 MySQL 的 EXPLAIN 来分析 SQL
笔记·sql·mysql
ybb_ymm2 小时前
如何通过跳板机链接mysql数据库
数据库·mysql
7ioik2 小时前
RC和RR隔离级别下MVCC的差异?
数据库·sql·mysql
luoluoal2 小时前
基于python的二维码生成算法研究和实现(源码+文档)
python·mysql·django·毕业设计·源码
高溪流2 小时前
2.Mysql相关概念 及 数据库操作
数据库·mysql
代码不停2 小时前
MySQL事务
android·数据库·mysql
IT_Octopus3 小时前
java 实体属性 Map 解决 mybatis-plus wrapper selectone 查mysql json类型为null 问题
java·mysql·mybatis