一文了解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秒"两个条件,才会被插入到新生代头部

相关推荐
m0_613856293 小时前
mysql如何利用事务隔离级别解决特定业务冲突_mysql隔离方案选型
jvm·数据库·python
Adios7944 小时前
VPR:Pitts50K和Norland数据集下载
数据库
东风破1374 小时前
DM用户权限、表、约束等对象的基本操作,SQL日志的开启介绍
数据库·sql·dm达梦数据库
wapicn994 小时前
微服务架构下的数据核验设计,API接入最佳实践
微服务·云原生·架构
收获不止数据库4 小时前
达梦9发布会归来:AI 时代,我们需要一款什么样的数据库?
数据库·人工智能·ai·语言模型·数据分析
小宇的天下4 小时前
Virtuoso GUI 界面中的关键模块定义
数据库
bqq198610264 小时前
MySQL 5.7 与 MySQL 8.0 的主要区别
数据库·mysql
juniperhan4 小时前
Flink 系列第21篇:Flink SQL 函数与 UDF 全解读:类型推导、开发要点与 Module 扩展
java·大数据·数据仓库·分布式·sql·flink
Ghost Face...4 小时前
龙芯2K1000 SoC启动全流程与架构解析
架构
侠客工坊5 小时前
移动端 RPA 的架构重构:基于侠客工坊多模态视觉大模型的自动化调度系统压测复盘
人工智能·智能手机·重构·架构·rpa·数字员工·侠客工坊