什么是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贝塔】进行体验,无限使用。

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

相关推荐
夏天吃哈密瓜20 分钟前
用Scala来解决成绩排名的相关问题
开发语言·后端·scala
爱编程的小生20 分钟前
SpringBoot Task
java·spring boot·后端
CoderJia程序员甲26 分钟前
重学SpringBoot3-异步编程完全指南
java·spring boot·后端·异步编程
岁岁岁平安32 分钟前
springboot实战(19)(条件分页查询、PageHelper、MYBATIS动态SQL、mapper映射配置文件、自定义类封装分页查询数据集)
java·spring boot·后端·mybatis·动态sql·pagehelper·条件分页查询
桃园码工1 小时前
第一章:Go 语言概述 1.什么是 Go 语言? --Go 语言轻松入门
开发语言·后端·golang
大明湖的狗凯.1 小时前
MySQL 中的乐观锁与悲观锁
java·数据库·mysql
真上帝的左手1 小时前
数据库-MySQL-MybatisPlus整合多数据源
数据库·mysql·mybatis
奈斯ing1 小时前
【MySQL篇】持久化和非持久化统计信息的深度剖析(第一篇,总共六篇)
数据库·mysql
真上帝的左手1 小时前
数据库-MySQL-Mybatis源码解析-设计模式角度
数据库·mysql·mybatis
萧萧玉树2 小时前
分布式在线评测系统
前端·c++·后端·负载均衡