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

相关推荐
烧瓶里的西瓜皮3 分钟前
Go语言从零构建SQL数据库引擎(2)
数据库·sql·golang
风象南16 分钟前
Spring Boot 实现文件秒传功能
java·spring boot·后端
橘猫云计算机设计17 分钟前
基于django优秀少儿图书推荐网(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·小程序·django·毕业设计
SelectDB20 分钟前
拉卡拉 x Apache Doris:统一金融场景 OLAP 引擎,查询提速 15 倍,资源直降 52%
大数据·数据库·数据分析
黑猫Teng21 分钟前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
爱的叹息22 分钟前
华为高斯(GaussDB) 集中式数据库 的开发技术手册,涵盖核心功能、开发流程、优化技巧及常见问题解决方案
数据库·gaussdb
小智疯狂敲代码22 分钟前
Java架构师成长之路-框架源码系列-整体认识Spring体系结构(1)
后端
背太阳的牧羊人26 分钟前
使用 PyMuPDF(fitz)库打开 PDF 文件,并且是从内存中的字节流(BytesIO)读取 PDF 内容
数据库·pdf·文件处理·pymupdf·fitz
星河浪人27 分钟前
Spring Boot启动流程及源码实现深度解析
java·spring boot·后端
雷渊1 小时前
深入分析Spring的事务隔离级别及实现原理
java·后端·面试