一文了解MySQL缓冲池buffer pool(作用 原理 淘汰策略 分配 刷新 配置)

对于MySQL的读请求来说,InnoDB维护了一个缓冲池 buffer pool,避免每次查询数据都进行磁盘IO,有效地减少了磁盘IO,提升了性能。

作用

缓冲池存储了最近访问或经常访问的数据页和索引页,当查询操作需要读取数据时,InnoDB首先在缓冲池里查找所需的页,如果找到了(命中),则无需访问磁盘,这样可以大大减少数据访问的延迟。

todo:缓冲区还缓存了最近修改的数据,这些数据在合适的时机会被写回到磁盘上,这个过程称为刷盘flush或写入write

工作原理

当一个数据页被访问的时候,会被加载到缓冲池里。如果该页已经在缓冲池中,则直接使用;如果不在,则在磁盘读取并放入缓冲池。

InnoDB会管理和淘汰缓冲池中的页,来保证只把最热的数据放在最近的地方,以最大限度地降低磁盘访问

管理与淘汰

预读

磁盘读取数据地时候是按页读取,一次至少读一页数据,一般是4K,如果未来要读取地数据就在页中,能够省去后续地磁盘IO,提高效率。这是因为局部性原理,数据访问一般都遵循集中读写的原则,使用一些数据,大概率会使用附近的数据。

所以,缓冲池一般也是按页缓存数据,把一些可能要访问的页提前加入缓冲池,避免未来的磁盘IO操作。

这里能想到的一点就是 缓存这边的预缓存策略。比如社区里返回一篇文章和下面的评论,把第一层评论的所有评论缓存一下。

那么InnoDB是用什么算法管理缓冲页的?

传统LRU

把入缓冲池的页放到LRU的头部,作为最近访问的元素,从而最晚被淘汰。

如果页已经在缓冲池里,就移动到LRU头部,没有页被淘汰;

如果页不在缓冲池里,放入LRU头部,淘汰LRU尾部页

但是这种算法用在MySQL这里就有2个问题:预读失效和缓冲池污染

预读失效

提前把页放入了缓冲池但是实际上并没有从页中读取数据

如何解决?

让预读失败的页,停留在缓冲池LRU里的时间尽可能短

让真正被读取的页,才能挪到缓冲池LRU的头部,这样可以保证真正被读取的热数据保留在缓冲池的时间尽可能长

具体方法

将LRU分为新生代和老生代两个部分,新老生代首尾相连,即,新生代后面是老生代

新页(例如被预读地页)加入缓冲池时,只加入到老生代头部

如果数据真正被读取(预读成功),才会被加入到新生代的头部

如果没有被读取,会币新生代的热数据页更早被淘汰出缓冲池

但是这样依旧解决不了缓冲池污染

缓冲池污染

当某一个SQL语句,需要批量扫描大量数据时,可能导致把缓冲池所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降

在扫描的时候,所有的数据页都会被加到新生代头部,但是只访问一次,真正的热数据被大量换出

如何解决?

使用老生代停留时间窗口的机制,假设T为老生代停留时间窗口,插入老生代头部的页,即使立刻被访问,也不会立刻被放入新生代头部。只有满足被访问并且在老生代停留时间大于T,才会被放入到新生代头部。

缓冲池的分配

缓冲池被划分为多个缓冲块Buffer Blocks,每个缓冲块通常为一页,页大小默认为16KB

缓冲池中的页可以是热页(频繁访问的页)或冷页(不常访问的页),InnoDB会根据访问频率动态调整这些页在缓冲池中的位置。

缓冲池的刷新

为了保证数据的持久性,InnoDB会定期将缓冲池中脏页(被修改的页)刷新回磁盘,这个过程可以通过多种方式触发,包括手动刷新、自动刷新、缓冲池满的页替换等

缓冲池的监控

SHOW ENGINE INNODB STATUS命令来查看缓冲池的当前状态

缓冲池实例

在多实例环境中,每个InnoDB实例都有自己的缓冲池,从MySQL5.7开始,支持多个缓冲池实例

缓冲池的配置和优化

缓冲池的大小和配置需要根据实际的工作负责和可用内存进行调整

innodb_buffer_pool_size:配置缓冲池的大小,在内存允许的情况下,DBA往往会建议调大这个参数,越多数据和索引放到内存里,数据库的性能会越好

innodb_old_blocks_pct:老生代占整个LRU链长度的比例,默认是37,即整个LRU中新生代与老生代长度比例是63:37。

innodb_old_blocks_time:老生代停留时间窗口,单位是毫秒,默认是1000,即同时满足"被访问"与"在老生代停留时间超过1秒"两个条件,才会被插入到新生代头部

相关推荐
豆角焖肉4 分钟前
SpringBoot + Redis 缓存实战
java·spring boot·redis·后端·缓存·菜单缓存
事圆则缓5 分钟前
聊天与引用回复的 SQL 怎么设计
数据库·sql
APItesterCris5 分钟前
告别反复手工查价:用 Open‑Claw 搭建商品监控与数据分析小工具
大数据·数据库·数据仓库·自动化
IT_陈寒9 分钟前
深入理解Redis:核心原理与最佳实践
前端·人工智能·后端
来福猿10 分钟前
分布式锁 Redis 实现源码分析:SETNX、过期时间与可重入设计
数据库·redis·分布式
打工仔折腾 AI11 分钟前
鸿蒙端ToDesk远控电脑实测:蓝牙键鼠、双模式鼠标与跨端剪贴板实践
后端·python·性能优化·计算机外设·电脑·harmonyos·ai agent 实战
xiangyun6115 分钟前
C++ list 模拟实现(一):手撕双向链表,从节点到迭代器
数据库·c++·算法·链表·stl·list
AINative软件工程16 分钟前
LLM 异步任务的 Webhook 工程实践:回调可靠投递、重试与幂等消费的生产设计
后端·ai编程
wespaul19 分钟前
一条自然语言命令的 49 个节点:可视化编排与每段强校验
前端·数据库
霸道流氓气质21 分钟前
Open Code Review 入门与实战:三阶段确定性流水线、LLM Agent 混合架构与 CI/CD 代码审查集成
ci/cd·架构·代码复审