MySQL之深入InnoDB存储引擎——Buffer Pool
文章目录
- 一、空闲链表的管理
- 二、缓冲页的哈希处理
- 三、Flush链表的管理
- 四、LRU链表的管理
- 五、脏页刷新
- 六、多Buffer Pool实例
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟,基于磁盘的数据库系统通常使用缓冲池技术来提高数据库的整体性能。在数据库中进行读取页的操作,首先将从磁盘读到的页存放在缓冲池中,这个过程称为将页“FIX”在缓冲池中,在下一次读取相同的页时,首先判断该页是否存在缓冲池中,如果存在则被命中,直接读取,否则读取磁盘上的页。
Buffer Pool对应的一片连续的内存被划分为若干个页面,页面大小和InnoDB表空间使用的页面大小一致,默认都是16KB。为了更好地管理Buffer Pool中的这些缓冲页,InnoDB为每个缓冲页都创建了一个控制块,其中包含该页所属的表空间编号、页号、缓冲页在Buffer Pool中的地址、链表节点等信息。控制块位于Buffer Pool的内存的前部分,缓冲页位于Buffer Pool的后部分,两部分之间可能会存在碎片(如果剩余的空间不足够再分配一堆控制块和缓冲页则会产生)。
一、空闲链表的管理
在我们最开始启动MySQL服务器的时候,需要向操作系统申请Buffer Pool的内存空间,然后把它换分成若干对控制块和缓冲页。当然此时没有真实的磁盘页被缓存到Buffer Pool中,会随着程序的运行不断缓存。
当从磁盘上读取到一个页时,我们需要将其放置在空闲的缓冲页中。那我们就需要区分哪些页是空闲的,哪些页已经被使用了,因此引入了Free链表(空闲链表)。在Buffer Pool刚刚完成初始化之后,所有缓冲页对应的控制块都会加入到空闲链表中。而为了管理这个空闲链表,我们为其定义了一个基节点,其中包含了链表的头节点地址、尾节点地址以及当前链表中节点的数量等信息。需要注意的是,链表的基节点占用的内存空间并不包含在为Buffer Pool申请的一大片连续内存孔内,而是一块单独申请的内存空间。
有了空闲链表之后,每当需要从磁盘中加载一个页到Buffer Pool中时,就从空闲链表中取一个缓冲页对应的控制块,把页加载到控制块指向的缓冲页中,并把该控制块的信息给填上(即表空间、页号等)。
二、缓冲页的哈希处理
使用了Buffer Pool之后,我们访问某个页的数据时会先去缓冲池中查找该页是否已经加载到内存中,如果不存在才会去磁盘中加载。而为了快速判断目标页是否存在于缓冲池中,InnoDB采用的是哈希表的方式,将表空间号和页号作为键,缓冲页控制块作为值来进行构建。
三、Flush链表的管理
如果我们修改了Buffer Pool中某个缓冲页的数据,那其中的数据就和磁盘中的不同了,此时这个缓冲页变为了脏页。虽然我们可以在每次修改完都将其刷新到磁盘中对应的页上,但是这显然会严重影响程序的性能。因此InnoDB不会在每次修改完页都立刻刷库,而是在未来某个时间点进行刷新。
既然不是及时刷新,那我们在未来刷新时便需要知道哪些页是脏页。因此引入了Flush链表进行脏页的管理,当缓冲页被修改则将其控制块加入到链表中。
和空闲链表相同,它也有一个相同结构的基节点来保存这个链表的信息。显然当一个缓冲页的控制块在空闲链表中时则不可能在Flush链表中,反之同理。
四、LRU链表的管理
Buffer Pool对应的内存大小毕竟是有限的,随着程序的运行Free链表总归会用完。如果Free链表已经没有多余的空闲缓冲页了,那么只能将某些旧的缓冲页从Buffer Pool中淘汰,再将新的页放进来。Buffer Pool引入的初衷是为了想减少磁盘IO,因此自然希望淘汰掉的页面是最少使用的,而最近经常使用的页面不被淘汰,因此InnoDB采用的淘汰策略为LRU,即最近最少使用算法。以这个算法为核心,InnoDB维护了一个LRU链表,如果页不在Buffer Pool中,在把该页从磁盘加载到Buffer Pool的时候,就把该缓冲页对应的控制块作为节点添加到LRU链表的头部,如果使用到链表中的某个页时也将其移动到链表头部。之后当空闲缓冲页用完时,就从链表尾部进行淘汰。
但这种实现并不完善,它存在两个问题:
-
因为InnoDB提供了预读的功能,即InnoDB认为执行当前的请求时,可能会在后面读取某些页面,于是就预先把这些页面加载到Buffer Pool中。根据触发方式的不同,预读可分为以下两种:
- 线性预读:InnoDB中有一个系统变量
innodb_read_ahead_threshold
,如果顺序访问某个区的页面超过这个系统变量的值,则会触发一次异步读取下一个区中所有页面的请求 - 随机预读:如果某个区的13个连续的页面都被加载到了Buffer Pool中,无论这些页面是不是顺序读取的,都会触发一次异步读取本区中所有其他页面到Buffer Pool中的请求。这个功能默认不会开启
- 预读到Buffer Pool中的页如果能够被成功的使用到,那自然可以极大地提高语句执行的效率。但是如果用不到,会导致LRU链表尾部的一些缓冲页很快就被淘汰掉,从而大大降低Buffer Pool的命中率
- 线性预读:InnoDB中有一个系统变量
-
有的时候可能需要用到全表扫描,这个过程中需要访问的页面一般会特别多,那么就会导致LRU链表中很多页面都会被淘汰掉。但是这次全表扫描引进来的这些页面可能并不是热点数据,但是反而把热点数据从链表中赶跑了
为了避免以上两种情况把Buffer Pool中真正的热点数据淘汰,InnoDB将LRU分成两个部分:
- 一部分存储使用频率非常高的缓冲页,称为热数据或young数据
- 一部分存储使用频率不是很高的缓冲页,称为冷数据或old数据
LRU的划分是根据比例的,默认情况下old区域占LRU链表的37%。之后当磁盘的页面被初次加载到Buffer Pool中时,该缓冲页对应的控制块会放置到old区域的头部,而不再是整个链表的头部,这样就不会使得预读加载进来的页影响young区域中使用比较频繁的缓冲页。并且在对某个处于old区域的缓冲页进行第一次访问时,会在它对应的控制块中记录下整个访问时间,如果后续的访问时间与第一次访问的时间在某个时间间隔内,那么该页面就不会从old区域移动到young区域头部。这样一来也可以防止全表扫描时除了将数据页加载到Buffer Pool,还会频繁读取页面中的记录导致仍然会淘汰掉热点数据的情况。
除了以上的改进,LRU还有进一步的优化策略。对于young区域的缓冲页来说,如果我们每次访问一个缓冲页都需要把它移动到LRU链表的头部,其实开销是比较大的,因为young区域都是热点数据。因此InnoDB规定只有被访问的缓冲页位于young区域1/4的后面时,才会被移动到LRU链表的头部。
五、脏页刷新
后台有专门的线程负责每隔一段时间就把脏页刷新到磁盘,这样可以不影响用户线程处理正常的请求,刷新的方式主要有两种:
- 从LRU链表的冷数据中刷新一部分页面到磁盘:后台线程会定时从LRU链表尾部开始扫描一些页面。如果在LRU链表中发现脏页(缓冲页的控制块就会记录该缓冲页是否被修改),则把它们刷新到磁盘
- 从Flsuh链表中刷新一部分到磁盘:后台线程也会定时从Flush链表中刷新一部分页面到磁盘,刷新的速率取决于当时系统是否繁忙
当有线程在准备加载一个磁盘页到Buffer Pool中时没有可用的缓冲页时会尝试查看LRU链表尾部,看是否存在可以直接释放掉的未修改缓冲页。有时后台线程刷新脏页的进度比较慢,导致LRU链表尾部的脏页还没有被刷新,此时则不得不将LRU链表尾部的一个脏页同步刷新到磁盘中,这会降低用户请求的速度。
六、多Buffer Pool实例
在多线程环境下,访问Buffer Pool中的各个链表都需要加锁处理。在Buffer Pool特别大并且多线程并发量特别高的情况下,单一的Buffer Pool可能会影响请求的处理速度。所以在Buffer Pool特别大时,可以把它们拆分成若干个小的Buffer Pool,每个Buffer Pool都称为一个实例。它们之间是相互独立的,多线程并发时不会互相影响。
相关文章:
MySQL之深入InnoDB存储引擎——Buffer Pool
文章目录 一、空闲链表的管理二、缓冲页的哈希处理三、Flush链表的管理四、LRU链表的管理五、脏页刷新六、多Buffer Pool实例 InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟&…...

网络安全(秋招)如何拿到offer?(含面试题)
以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题…...
笙默考试管理系统-MyExamTest----classranking(2)
笙默考试管理系统-MyExamTest----classranking(2) 目录 笙默考试管理系统-MyExamTest----classranking(2) 一、 笙默考试管理系统-MyExamTest----classranking 二、 笙默考试管理系统-MyExamTest----classranking 三、 笙…...
基于python的一个元素多种定位方式
基于 Python 的 Page Factory 设计模式测试库, 类似于Java的Page Factory模式,旨在减少代码冗余,简单易用,具有高度的可扩展能力。 支持以annotation的方式定义元素 支持同一个元素多种定位方式 支持动态的定位方式 安装 pip install pyth…...

Fastdfs集群搭建
一、简单介绍: FastDFS是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件&…...

【深度学习】Vision Transformer论文,ViT的一些见解《 一幅图像抵得上16x16个词:用于大规模图像识别的Transformer模型》
必看文章:https://blog.csdn.net/qq_37541097/article/details/118242600 论文名称: An Image Is Worth 16x16 Words: Transformers For Image Recognition At Scale 论文下载:https://arxiv.org/abs/2010.11929 官方代码:https:…...

在centos7上使用非编译方式安装ffmpeg
很多在centos7上安装ffmpeg的教程都需要使用编译方式的安装;编译时间较长而且需要配置; 后来搜索到可以通过加载rpm 源的方式实现快速便捷操作 第一种方式: 首先需要安装yum源: yum install epel-release yum install -y https://mirrors.…...
【微信小程序】导出Excel文件
// 导出 doOutExcel() {let fileName 考勤列表wx.request({url: XXX,method: POST,header: {"content-type": "application/json","Authorization": "token " wx.getStorageSync(userInfo).token},data: {}, // 请求参数responseTyp…...

接口测试—知识速查(Postman)
文章目录 接口测试1. 概念2. 原理3. 测试流程4. HTTP协议4.1 URL的介绍4.2 HTTP请求4.2.1 请求行4.2.2 请求头4.2.3 请求体4.2.4 完整的HTTP请求示例 4.3 HTTP响应4.3.1 状态行4.3.2 响应头4.3.3 响应体4.3.4 完整的HTTP请求示例 5. RESTful接口规范6. 测试用例的设计思路6.1 单…...

机器学习深度学习——序列模型(NLP启动!)
👨🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——卷积神经网络(LeNet) 📚订阅专栏:机器学习&&深度…...

小白到运维工程师自学之路 第六十四集 (dockerfile构建tomcat、mysql、lnmp、redis镜像)
一、tomcat(更换jdk) mkdir tomcat cd tomcat/ tar xf jdk-8u191-linux-x64.tar.gz tar xf apache-tomcat-8.5.40.tar.gzvim Dockerfile FROM centos:7 MAINTAINER Crushlinux <syh163.com> ADD jdk1.8.0_191 /usr/local/java ENV JAVA_HOME /us…...

超低功耗水表电器表LCD驱动显示芯片,高抗干扰性能提供LQFP48、LQFP64的封装
VK2C23是一个点阵式存储映射的LCD驱动器,可支持最大224点(56SEGx4COM)或者最大416点(52SEGx8COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰ÿ…...

SpringBoot3---核心特性---2、Web开发III(模板引擎、国际化、错误处理)
星光下的赶路人star的个人主页 夏天就是吹拂着不可预期的风 文章目录 1、模板引擎1.1 Thymeleaf1.2 基础语法1.3 属性设置1.4 遍历1.5 判断1.6 属性优先级1.7 行内写法1.8 变量选择1.9 模板布局1.10 devtools 2、国家化3、错误处理3.1 默认机制3.2 自定义错误响应3.3 最佳实战 …...

MemFire教程|FastAPI+MemFire Cloud+LangChain开发ChatGPT应用-Part2
基本介绍 上篇文章我们讲解了使用FastAPIMemFire CloudLangChain进行GPT知识库开发的基本原理和关键路径的代码实现。目前完整的实现代码已经上传到了github,感兴趣的可以自己玩一下: https://github.com/MemFire-Cloud/memfirecloud-qa 目前代码主要…...
C# File.Exists与Directory.Exists用法
File.Exists: 用于检查给定文件路径是否存在。如果文件存在,则返回true,否则返回false。 string path“D:\\test\\example.txt” bool exists File.Exists(path); if (exists) {Console.WriteLine("File exists."); } else {Con…...
(深度学习,自监督、半监督、无监督!!!)神经网络修改网络结构如何下手???
修改神经网络结构,我们可以根据这个进行添加: 卷积层(Convolutional Layers):标准的卷积层用于提取特征并进行特征映射。 池化层(Pooling Layers):用于减少特征图的空间维度&…...

Codejock Task Panel ActiveX Crack
Codejock Task Panel ActiveX Crack ActiveX COM的Codejock任务面板为Windows开发人员提供了一个复杂的Office任务面板,类似于在Microsoft Office和Windows资源管理器中看到的内容。TaskPanel甚至可以用作Visual Studio风格的工具箱。 功能概述 ActiveX COM的Codejo…...

LeetCode 热题 100 JavaScript--141. 环形链表
给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(…...

文字转语音
键盘获取文字,转化为语音后保存本地 from win32com.client import Dispatch from comtypes.client import CreateObject from comtypes.gen import SpeechLib speakerDispatch(SAPI.SpVoice) speaker.Speak(请输入你想转化的文字) datainput(请输入:)#s…...
让ELK在同一个docker网络下通过名字直接访问
1. docker网络 参考https://blog.csdn.net/lihongbao80/article/details/108019773 https://www.freecodecamp.org/chinese/news/how-to-get-a-docker-container-ip-address-explained-with-examples/ 默认网络有三种,分别是 1、bridge模式,–netbridge(…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...