【MySQL】深入解析 Buffer Pool 缓冲池

文章目录

    • 1、前置知识
      • 1.1、Buffer Pool介绍
      • 1.2、后台线程
        • 1.2.1、Master Thread
        • 1.2.2、IO Thread
        • 1.2.3、Purge Thread
        • 1.2.4、Page Cleaner Thread
      • 1.3、重做日志缓冲池
    • 2、Buffer Pool 组成
      • 2.1、数据页
      • 2.2、索引页
      • 2.3、插入缓冲
      • 2.4、锁空间
      • 2.5、数据字典
      • 2.6、自适应哈希索引
    • 3、Buffer Pool 内存管理
      • 3.0、控制块
      • 3.1、Free List
      • 3.2、Flush List
      • 3.3、LRU List

1、前置知识

1.1、Buffer Pool介绍

MySQL数据库具有可拔插存储引擎,其中最常用的是InnoDB,而Buffer Pool缓冲池InnoDB存储引擎中特有的内存结构,MySQL向操作系统内存申请一块内存空间用于Buffer Pool缓冲池使用,因为硬盘和内存性能差距大,所以Buffer Pool缓冲池用于协调CPU速度和硬盘速度的鸿沟,Buffer Pool大幅度提升MySQL数据库的读写性能。

按照我们的惯性思维,这里会有一个疑问:不都说MySQL的数据是基于硬盘存储吗,为什么这里会提到Buffer Pool缓冲池内存这概念?

MySQL当然是通过硬盘持久化存储Buffer Pool 并不是 MySQL 真正意义上存储数据的单元载体。
MySQL仅仅是借助Buffer Pool提升读写性能,毕竟内存的访问速度要比硬盘快得多!这并不冲突。

我们进行数据的查询操作,MySQL并不是直接从硬盘文件中查找对应的数据信息,会先查看Buffer Pool中是否有想要查询数据。如果有,直接返回给用户;如果没有,去硬盘中的查询想要的数据。查询到结果后会同步到Buffer Pool中,下次用户再次发起查询就不用访问磁盘了,修改操作也是同理(先操作Buffer Pool中的数据,然后数据刷入硬盘的文件中,有点像Redis),我们先站在操作系统维度看看 Buffer Pool 在内存中的样貌:
在这里插入图片描述
Buffer Pool缓冲池数据页,硬盘中MySQL表数据加载到Buffer Pool中就是通过数据页来存放的,Buffer Pool默认大小128MBInnoDB存储引擎已经将硬盘中的数据划分为一个个,默认大小16KB,通过为基本单位,进行硬盘内存之间的交互。

上面提到了查询、修改等SQL操作,无论是Buffer Pool将修改的页刷盘到硬盘,还是从硬盘加载到Buffer Pool,都是以数据页为单元进行操作的,而不是操作中的某几行数据。

这里有个注意点,Buffer Pool缓冲池并不是只有一个的,可以申请多个内存区域作为缓冲池同时工作。

1.2、后台线程

之前提到一个概念叫做刷盘,意思是Buffer Pool中缓存页数据会异步刷新到硬盘中,保证了数据的一致性,后台线程的主要作用就是对缓冲池中的页进行进行操作。InnoDB存储引擎后台线程主要有以下几种:
在这里插入图片描述

1.2.1、Master Thread

该线程主要用于将Buffer Pool 缓冲池中的数据进行刷盘,保证数据一致性。主要主责包括:脏页刷盘、插入缓冲合并、undo页回收等。

1.2.2、IO Thread

该线程主要用于处理AIO(Async IO)请求回调,因为InnoDB存储引擎中存在大量的异步IO操作,IO Thread可以极大数据库性能。

1.2.3、Purge Thread

事务提交之后,undo页就没有任何存在的意义了,该线程主要职责就是回收无用的undo页

上面1.2.1 Master Thread中提到,Master Thread主要职责就包括了回收undo页,但是后续InnoDB版本开始将部分purge操作交给Purge Thread来完成,减少Master Thread的工作压力,提升性能。也就是说回收undo页功能Master ThreadPurge Thread都具备,该线程就是为了替Master Thread分担回收undo页的工作压力。

1.2.4、Page Cleaner Thread

该线程也是为Master Thread分担工作压力,提升数据库性能。不过Page Cleaner Thread分担了什么压力呢?脏页刷盘操作。

1.3、重做日志缓冲池

硬盘中存在重做日志文件,主要用于故障恢复,保证MySQL事务的持久性,重做日志缓冲池就是用于存放重做日志信息,然后按照一定频率刷盘重做日志文件中,常用于数据库的故障恢复场景,这并不是本文章的重点。

2、Buffer Pool 组成

2.1、数据页

当我们进行查询的数据不在缓冲池中时,就会将磁盘中的数据对应的页加载到Buffer Pool中,这就是数据页。当我们对数据页内容进行修改,此时数据页就会变成脏页,而不是直接操作硬盘中的文件页,只需要将脏页刷新到磁盘中,这样通过为单位交互性能好很多。
在这里插入图片描述

2.2、索引页

Buffer Pool缓冲池中,不仅会存放数据页,还会存放索引页

之所以这样,是因为我们不能保证每次查询操作都能从缓冲池的数据页中拿到想要的结果,此时就需要对磁盘中数据文件进行IO访问操作。如果本次的查询操作命中了索引,我们又该如何知道索引的根节点到底在磁盘中的哪个位置呢?这个时候就需要索引页来帮助我们,当MySQL实例启动时,就会将数据库中的索引根节点放入到缓冲池的索引页中,当我们的查询SQL命中了索引,就不需要在整个磁盘中查找对应的索引根节点了!

2.3、插入缓冲

插入缓冲只针对非聚集、不唯一索引页增、删、改操作。

当我们对非聚集、不唯一索引页进行插入、修改操作时,不是直接操作索引页,而是先判断当前索引页是否在Buffer Pool缓冲池中,如果在直接操作索引页即可,如果不在就放入Insert Buffer对象中,然后以一定频率进行插入缓冲和辅助索引页合并操作,大大提升非聚集索引操作性能!

那为什么聚集索引或者说主键索引不需要插入缓冲?因为主键索引插入操作是按照主键顺序递增的,属于顺序插入,不需要随机读取硬盘,性能很快。

2.4、锁空间

锁空间就是专门用来存储锁结构、并发事务的链表的一块内存区域,这里不过多介绍。

2.5、数据字典

MySQL数据库启动时,会自动从硬盘中将系统表相关信息加载到Buffer Pool缓冲池中,有了数据字典,这样当我们使用show indexshow tables相关命令就能查到表、索引相关的信息,主要分为以下:

SYS_TABLES:存储所有InnoDB表信息。
SYS_COLUMNS:存储所有用户定义的表字段信息。
SYS_INDEXES:存储所有InnoDB引擎表索引信息。
SYS_FIELDS:存储所有索引的定义信息。

2.6、自适应哈希索引

默认情况下,我们的索引页采用B+Tree的结构,大幅度提高我们对数据库的查询性能,虽然性能已经很好了,但是自适应哈希索引的性能棒不得了!O(1)时间复杂度,查询性能非常高。

自适应哈希索引不需要我们主动人为干涉,它是InnoDB自动生成的,自适应哈希索引针对是热点索引页,而不是整张表,并且生成的条件也比较苛刻。当我们对某个索引页连续的访问模式条件一样,访问模式例如:

where a = xxx
where a = xxx and b = yyy

上面举例这两种访问模式不能交替执行,否则也不会生成自适应哈希索引,那何时自动生成呢,有以下两种情况:

以某个模式访问100次
以某个模式访问 n 次(n = 页中记录 / 16)

3、Buffer Pool 内存管理

3.0、控制块

InnoDB在操作系统中为Buffer Pool缓冲池申请创建了一块连续的内存,内存被划分成一块块缓冲页(之前提过缓冲池是以页为基本单位与磁盘进行交互),InnoDB存储引擎为缓冲池中每个缓冲页都生成了一个控制块,一对一关系。

控制块中记录了数据页所属的表空间、页号、缓冲页地址、链表节点指针等信息。控制块缓存页关系图如下:发现图中有个内存碎片,这是因为缓冲池剩余空间不够一对控制块和缓存页的大小,这点剩余内存空间就被称为内存碎片
在这里插入图片描述

3.1、Free List

Buffer Pool缓冲池内存被划分为一个个,但并不是所有都被使用,有一些是处于空闲状态的(没存数据),这种空闲页会被Free List进行管理,方便快速查找使用。

当硬盘中的页刷入到Buffer Pool缓冲池中时,就会从Free List中查找是否有空闲页,如果有,就将空闲页Free List中取出使用(移除);如果没有,就会使用后续提到的LRU List列表的尾部的数据页。下图中头节点解释:

head:指针,指向 Free List 的第一个控制块。
ail:指针,指向 Free List 的最后一个控制块。
count:数字,记录 Free List 的节点数量。

在这里插入图片描述

3.2、Flush List

之前提到过脏页刷盘这个操作,所谓脏页就是缓冲池缓存页中内容发生了改变(修改、删除、新增),此时这个该页就称为脏页。脏页数据和磁盘中文件数据是不一致的,需要后台线程将数据异步刷新到磁盘中。这些脏页的管理就需要Flush List,结构图跟3.1 Free List大同小异,这里就不重复画了。

3.3、LRU List

知道了Free List维护空闲页Flush List维护脏页,那么LRU List维护的是什么页?

LRU List用来管理已经读取的页,所以当数据库刚启动时,LRU List也是空的,这时候的空闲页都在Free List中,当需要从硬盘中加载数据页到Buffer Pool时,就会从Free List查找是否有空闲页可以使用,如果没有空闲页就根据LRU算法淘汰LRU List尾部页,将内存空间分配给新页。

硬盘中的页加载到缓冲池中,没有任何修改操作,那就说这个缓冲页是干净的(干净页),或者说脏页数据刷盘到磁盘后,就变成了干净页。不过有一点需要强调,当我们对干净页进行修改操作时,也就是它变成了脏页,此时脏页也不会从LRU List中移除,这个脏页将会同时存在于LRU ListFlush List中。

关于脏页是否同时在LRU、Flush List中存在,这里有些争议,有些人认为脏页不在LRU List中记录,只在Flush List中记录;
不过《MySQL技术内幕 InnoDB存储引擎》这本书中介绍的是:脏页既存在于LRU List,也存在于Flush List

LRU List管理缓存页是通过LRU算法,就是说访问频率低(最近最少使用)的缓存页将会放到LRU List列表尾部,访问频率比较高的热点页将会放到LRU List首部,当可用的空闲页不足时,就会淘汰LRU List链表末尾的数据页。我们先来看下LRU List大致是什么样子:
在这里插入图片描述
LRU ListLRU算法跟常规的LRU算法是有区别的,InnoDB之所以使用特殊的LRU算法,主要是考虑到传统的LRU算法有这两个问题:

  • 预读无效
  • Buffer Pool污染

预读的意思是 Buffer Pool 在加载数据页时,会把它相邻的数据页一起加载到缓冲池中,目的是减少了磁盘IO操作。不过常规LRU算法会将预读的数据页也放置到LRU List头部,这样可能出现预读数据页几乎不会使用到(大大降低LRU List的使用性能)。

Buffer Pool污染大概也是这个意思,如果偶尔做一次大数据量的表查询操作(全表扫描),直接出现许多不常用数据页在LRU List头部,导致本身的热点页被移除。降低了LRU List使用性能。

针对以上常规LRU算法所带来的问题,LRU List是用了特殊LRU算法。上图中可以看到midpoint,通过midpoint为分界线,将midpoint左侧数据页区域称为NEW区,右侧称为OLD区。NEW区域的数据页是经常使用、访问的,这些数据页我们称之为热点页midpoint位于LRU List链表的5/8处(37 : 63),这个比例可以通过参数innodb_old_blocks_pct调整,这样我们最新访问的数据页不会直接放到NEW区域的头部,而是放到OLD区域的头部。

那么什么时候会从OLD区移动到NEW区呢?InnoDB存储引擎通过一个时间参数innodb_old_blocks_time控制页读取到midpoint位置时,等待多久才会加入到NEW区,这个时间默认为1000ms。如果后续的访问时间与第一次访问的时间不在这个时间间隔内,那么该缓存页就会移动到 NEW 区域的头部,这就是LRU List管理缓存页的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/415922.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库JSON类型到映射JAVA上

Mysql存放JSON数据如何映射JAVA实体类 概述:最近写在写SKU模块中,需要表中字段存放JSON类型数据,mybatis-plus在查询的时候如何跟JSON类型所匹配呢?再次记录一下。 直接上代码,后面有解释到底如何映射上的。 Mysql表…

MySql-多表设计-一对一

目录 一对一 一对一 一对一关系表在实际开发中应用起来比较简单,通常是用来做单表的拆分,也就是将一张大表拆分成两张小表,将大表中的一些基础字段放在一张表当中,将其他的字段放在另外一张表当中,以此来提高数据的操…

【二】【SQL】去重表数据及分组聚合查询

去重表数据 表的准备工作 去除表中重复的数据,重复的数据只留一份。 mysql> create table duplicate_table (-> id int,-> name varchar(20)-> ); Query OK, 0 rows affected (0.03 sec)mysql> insert into duplicate_table values-> (100,aaa)…

Socket网络编程(一)——网络通信入门基本概念

目录 网络通信基本概念什么是网络?网络通信的基本架构什么是网络编程?7层网络模型-OSI模型什么是Socket?Socket的作用和组成Socket传输原理Socket与TCP、UDP的关系CS模型(Client-Server Application)报文段牛刀小试(TCP消息发送与接收&#…

【Unity】实现从Excel读取数据制作年份选择器

效果预览: 此处利用Excel来读取数据来制作年份选择器,具体步骤如下。 如果只是制作年份选择器可以参考我这篇文章:构建简单实用的年份选择器(简单原理示范) 目录 效果预览: 一、 Excel准备与存放 1.1 …

【问题解决】| conda不显示指示前面的(base)无法在终端激活虚拟环境

1 遇到的问题 就是在安装好conda,配置好环境变量后 可以正常用conda的指令,如创建环境等等 但是不能激活新建的环境,我们知道同时也没有前面的小括号指示当前环境,也没有这个前面的(base) 2 解决方式 有一些方法如&#xff0c…

nginx 日志,压缩,https功能介绍

一, 自定义访问日志 (一)日志位置存放 1,格式 2, 级别 level: debug, info, notice, warn, error, crit, alert, emerg 3,示例 服务机定义 错误日志存放位置 客户机错误访问 查看错误日志 4&#xff…

table展示子级踩坑

##elemenui中table通过row中是否有children进行判断是否展示子集,通过设置tree-prop的属性进行设置,子级的children的名字可以根据自己的子级名字进行替换,当然同样可以对数据处理成含有chilren的子级list。 问题: 1.如果是根据后…

基于springboot+vue的共享汽车管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

云计算与边缘计算:有何不同?

公共云计算平台可以帮助企业充分利用全球服务器来增强其私有数据中心。这使得基础设施能够扩展到任何位置,并有助于计算资源的灵活扩展。混合公共-私有云为企业计算应用程序提供了强大的灵活性、价值和安全性。 然而,随着分布在全球各地的实时人工智能应…

WPF margin属性学习

一开始margin如下,显示如下; margin有四个值的时候是left、top、right、bottom; 如果是Margin“20,10”,则是指left、right设置为20,top、bottom设置为10; 看上去有些问题,现在top为负&#xf…

JAVA泛型浅析

Java范型generics,是JDK1.5引入的新特性,是一种编译时类型安全检测机制,可以在编译时检测到非法的类型。范型的本质是将类型参数化,将类型指定成一个参数。java中的集合就有使用,并且对外提供的三方库和SDK中使用也极为…

【ElfBoard】基于 Linux 的智能家居小项目

大家好,我是 Hello阿尔法,这段时间参与了保定飞凌嵌入式技术有限公司举办的 ElfBoard 共创社招募活动,并有幸成为了一名共创官,官方寄来了一块 ELF 1 开发板,开箱看这里 ELF 1 开箱初体验。 作为共创官,我…

NoSQL--虚拟机网络配置

目录 1.初识NoSQL 1.1 NoSQL之虚拟机网络配置 1.1.1 首先,导入预先配置好的NoSQL版本到VMware Workstation中 1.1.2 开启虚拟机操作: 1.1.2.1 点击开启虚拟机: 1.1.2.2 默认选择回车CentOS Linux(3.10.0-1127.e17.x86_64) 7 …

3DGS学习(六)—— 参数更新

参数更新 参考文章:3dgs中的数学推导 协方差矩阵的参数更新 直接通过pytorch自带的更新机制,通过渲染后计算损失,只能更新2D协方差矩阵 Σ ′ \Sigma^\prime Σ′,再通过公式逆推出3d空间协方差矩阵 Σ \Sigma Σ的值。该过程处…

【Linux】云服务器的Redis被黑

📝个人主页:五敷有你 🔥系列专栏:Linux ⛺️稳中求进,晒太阳 攻击发现: 这个异常情况是在腾讯云被入侵后,短信提醒发现的。并没有系统的学习过关于服务器安防相关的知识,遇到…

三天学会阿里分布式事务框架Seata-SpringCloud Alibaba分布式基础案例搭建

锋哥原创的分布式事务框架Seata视频教程: 实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)共计10条视频&…

10 在线逻辑分析仪的使用

在线逻辑分析仪简介 传统的 FPGA 板级调试是将逻辑分析仪连接到 FPGA 的 IO 引脚上 ,然后将内部信号引出至 IO 引脚,再进行板级调试,这种方法的缺点是我们需要一个逻辑分析仪,且还要在 PCB 中预留测试点。在线逻辑分析仪克服了以…

配电房轨道式巡检机器人方案

一、应用背景 在变电站、配电房、开关站等各种室内变配电场所内,由于变配电设备的数量众多、可能存在各类安全隐患,为了保证用电的安全可靠,都要进行日常巡检。 但目前配电房人工巡检方式有以下主要问题: 巡检工作量大、成本高 …

三、西瓜书——神经网络

一、神经元模型 在M-P神经网络模型中,神经元接 收到来自n个其他神经元传递过来的输入信号,这些输入信号通过带权重的连接(connection)进行传递,神经元接收到的总输入值将与神经元的阈值进行比较,然后通过“激活函数”(activation …