什么是MySQL的"内存数据加速器"——Buffer Pool?

在往期文章中有聊到什么是数据库的事务,以及更新事务的实现流程是怎么样的,在文章中我们提到过更新事务的实际流程其实有涉及到 Buffer Pool,本次就简单聊聊什么是 Buffer Pool。对于事务的更新流程感兴趣的童鞋可参考历史文章;

什么是数据库事务?更新事务实现流程是怎样的

我们都知道,MySQL 的数据(除了 Memory 引擎外)都存储在磁盘上。然而,若每次查询和修改都直接与磁盘交互,性能将会非常低下。

因此,为了提升读写性能,Innodb 引擎引入了一个中间层,即缓冲池(buffer pool)。

缓冲池是内存中一块连续的空间,主要用于缓存数据页。每个数据页的大小为 16KB。

页是 Innodb 进行数据存储的基本单元,无论是在磁盘还是在缓冲池中,数据的读取都是以页为单位进行的,这也体现了一种"预读"的思想。

有了缓冲池之后,当我们进行数据查询时,InnoDB 会首先检查缓冲池中是否存在该数据。如果存在,数据就可以直接从内存中获取,避免了频繁的磁盘读取,从而提高查询性能。如果不存在,则会去磁盘中读取数据,并将找到的数据页复制到缓冲池中,再返回给客户端。这样,后续的查询可以直接从缓冲池中就近读取数据。

当需要进行数据修改时,操作也会先在缓冲池中进行,然后再将修改后的数据写入磁盘。

然而,由于缓冲池是基于内存的,其空间不可能无限大,默认大小为 128M。当然,这个大小并不是固定的,我们可以通过修改 MySQL 配置文件中的 innodb_buffer_pool_size 参数来调整缓冲池的大小。

bash 复制代码
# 查看buffer pool
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';


# 修改buffer pool
SET GLOBAL innodb_buffer_pool_size = 512M;

扩展知识

InnoDB 的数据页

上面提到了 InnoDB 的数据页,它和 B+树的关系是怎样的呢?

InnoDB 的数据页是其存储引擎中用于存储数据的基本单位。数据页在磁盘上是一个连续的区域,通常大小为 16KB,当然也可以通过配置进行调整。16KB 意味着 InnoDB 的每次读写操作都是以 16KB 为单位的,即一次从磁盘读取到内存的最小单位是 16KB,从内存写入到磁盘的最小单位也是 16KB。

在 B+树结构中,每个节点都对应着一个数据页,包括根节点、非叶子节点和叶子节点。B+树通过节点之间的指针连接不同层级的数据页,从而构建出一个有序的索引结构。

通过 B+树的搜索过程,可以从根节点开始逐层遍历,最终到达叶子节点,找到所需的数据行。

因此,数据页是存储数据行的实际物理空间,以页为单位进行磁盘读写操作。B+树通过节点和指针的组织,构建了一个层次结构的索引,用于快速定位和访问数据行。

B+树的非叶子节点对应着数据页,其中存储着主键及指向子节点(即其他数据页)的指针。B+树的叶子节点包含实际的数据行,每个数据行存储在一个数据页中。

通过这种方式,InnoDB 利用 B+树和数据页的组合,实现了高效的数据存储和检索。B+树提供了快速的索引查找能力,而数据页提供了实际存储和管理数据行的机制。它们相互配合,使得 InnoDB 能够处理大规模数据的高效访问。

数据页的构成

一个数据页包含七个部分,分别是文件头、页头、最小和最大记录、用户记录、空闲空间、页目录以及文件尾。

buffer pool 和 query cache 的区别

在 InnoDB 中,除了缓冲池(Buffer Pool),还有另一个缓存层用于数据缓存,提升查询效率。很多人容易混淆它与缓冲池的区别。

首先,它们的目的和作用不同。缓冲池用于缓存表和索引的数据页,从而加速读取操作;而查询缓存(Query Cache)用于缓存查询结果,减少重复查询的执行时间。

缓冲池主要与存储引擎 InnoDB 相关,而查询缓存也支持其他引擎,如 MyISAM 等。因此,查询缓存位于服务器层的优化技术,而缓冲池位于引擎层的优化技术。

需要注意的是,在 MySQL 5.7 版本中,查询缓存已经被标记为废弃,并在 MySQL 8.0 版本中彻底被移除。

buffer pool 的读写过程是怎么样的?

MySQL 的缓冲池(Buffer Pool)是一个内存区域,用于缓存数据页,从而提高查询性能。读写过程涉及将数据从磁盘读取到内存、在内存中进行修改,并最终写回磁盘。

读过程

当我们在 MySQL 执行一个查询请求时,其过程如下:

  1. MySQL 首先检查缓冲池(Buffer Pool)中是否存在本次查询的数据。如果数据在缓冲池中,就直接返回结果。
  2. 如果数据不在缓冲池中,MySQL 会从磁盘读取数据。
  3. 读取的数据页被放入缓冲池,同时 MySQL 会将请求的数据返回给应用程序。

读取过程相对简单,而缓冲池的写入过程则稍显复杂。

写过程

当执行一次更新语句(如 INSERT、UPDATE 或 DELETE)时,MySQL 的过程如下:

  1. 应用程序执行写操作时,MySQL 首先将要修改的数据页加载到缓冲池(Buffer Pool)中。
  2. 在缓冲池中,对数据页进行修改,以满足写请求。这些修改只在内存中进行,不会立即写回磁盘。
  3. 如果缓冲池中的数据页被修改过,MySQL 会将这个页标记为"脏页"(Dirty Page)。
  4. 脏页会被后台线程写回磁盘,这个过程称为脏页刷盘。写入操作完成后,数据得以持久化。

需要注意的是,脏页的写回磁盘是由后台线程进行的。在 MySQL 服务器空闲或负载较低时,InnoDB 会执行脏页刷盘操作,以减少对用户线程的影响,从而降低性能的影响。

参考文档:dev.mysql.com/doc/refman/...

上图来自文章: 什么是数据库事务?更新事务实现流程是怎样的

感兴趣的可自行阅读

当脏页的百分比达到innodb_max_dirty_pages_pct_lwm变量定义的低水位标记时,将启动缓冲池的刷新。缓冲池页的默认低水位标记为 10%。将innodb_max_dirty_pages_pct_lwm值设为 0 会禁用这种提前刷新行为。

InnoDB 还采用了一种适应性刷新算法,根据 redo log 的生成速度和当前的刷新率动态调整刷新速度。其目的是通过确保刷新活动与当前工作负载保持同步,来平滑整体性能。

当然,我们也可以通过执行SET GLOBAL innodb_buffer_pool_dump_now=ON来手动触发脏页刷新到磁盘。

此外,在 MySQL 服务器正常关闭或重启时,所有的脏页都会被刷新到磁盘,以确保数据持久化。

如有问题,欢迎微信搜索【码上遇见你】。

免费的Chat GPT可微信搜索【AI贝塔】进行体验,无限使用。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

相关推荐
tan180°5 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
DuelCode6 小时前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
优创学社26 小时前
基于springboot的社区生鲜团购系统
java·spring boot·后端
why技术6 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
幽络源小助理6 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
ai小鬼头7 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
简佐义的博客7 小时前
破解非模式物种GO/KEGG注释难题
开发语言·数据库·后端·oracle·golang
爬山算法7 小时前
MySQL(116)如何监控负载均衡状态?
数据库·mysql·负载均衡
Code blocks8 小时前
使用Jenkins完成springboot项目快速更新
java·运维·spring boot·后端·jenkins