Mysql InnoDB的Buffer Pool

news2024/12/28 6:06:42

Buffer Pool

在MySQL服务器启动的时候就向操作系统申请了⼀⽚连续的内存,他们给这⽚内存起了个名,叫做Buffer Pool(中⽂名
是缓冲池)。
默认情况下Buffer Pool只有128M⼤⼩,最⼩值为5M,通过修改配置文件设置其大小(256M):
[server]
innodb_buffer_pool_size = 268435456

Buffer Pool内部组成

Buffer Pool中默认的缓存⻚⼤⼩和在磁盘上默认的⻚⼤⼩是⼀样的,都是16KB。为了更好的管理这些在Buffer Pool中的缓存⻚,设计InnoDB的为每⼀个缓存⻚都创建了⼀些所谓的控制信息,这些控制信息包括该⻚所属的表空间编号、⻚号、缓存⻚在Buffer Pool中的地址、链表节点信息、⼀些锁信息以及LSN信息。
每个缓存⻚对应的控制信息占⽤的内存⼤⼩是相同的,每个⻚对应的控制信息占⽤的⼀块内存称为⼀个控制块吧,控制块和缓存⻚是⼀⼀对应的,它们都被存放到 Buffer Pool 中,其中控制块被存放到 Buffer Pool 的前边,缓存⻚被存放到 Buffer Pool 后边,所以整个Buffer Pool对应的内存空间。
每⼀个控制块都对应⼀个缓存⻚,那在分配⾜够多的控制块和缓存⻚后,可能剩余的那点⼉空间不够⼀对控制块和缓存⻚的⼤⼩,这个⽤不到的那点⼉内存空间就被称为碎⽚
在这里插入图片描述

free链表的管理

把所有空闲的缓存⻚对应的控制块作为⼀个节点放到⼀个链表中,这个链表也可以被称作free链表,如下:
在这里插入图片描述
每当需要从磁盘中加载⼀个⻚到Buffer Pool中时,就从free链表中取⼀个空闲的缓存⻚,并且把该缓存⻚对应的控制块的信息填上(就是该⻚所在的表空间、⻚号之类的信息),然后把该缓存⻚对应的free链表节点从链表中移除,表示该缓存⻚已经被使⽤了。

缓存页的哈希处理

当我们需要访问某个⻚中的数据时,就会把该⻚从磁盘加载到Buffer Pool中,⽤表空间号 + ⻚号作为key,缓存⻚作为value创建⼀个哈希表,在需要访问某个⻚的数据时,先从哈希表中根据表空间号 + ⻚号看看有没有对应的缓存⻚,如果有,直接使⽤该缓存⻚就好,如果没有,那就从free链表中选⼀个空闲的缓存⻚,然后把磁盘中对应的⻚加载到该缓存⻚的位置。

flush链表的管理

如果我们修改了Buffer Pool中某个缓存⻚的数据,那它就和磁盘上的⻚不⼀致了,这样的缓存⻚也被称为脏页(英⽂名:dirty page)。
凡是修改过的缓存⻚对应的控制块都会作为⼀个节点加⼊到⼀个链表中,因为这个链表节点对应的缓存⻚都是需要被刷新到磁盘上的,所以也叫flush链表。链表的构造和free链表差不多,假设某个时间点Buffer Pool中的脏⻚数量为n。
在这里插入图片描述

LRU链表的管理

当Buffer Pool中不再有空闲的缓存⻚时,就需要淘汰掉部分最近很少使⽤的缓存⻚。

简单的LRU链表

只要我们使⽤到某个缓存⻚,就把该缓存⻚调整到LRU链表的头部,这样LRU链表尾部就是最近最少使⽤的缓存⻚。

划分区域的LRU链表

⼀部分存储使⽤频率⾮常⾼的缓存⻚,所以这⼀部分链表也叫做热数据,或者称young区域
另⼀部分存储使⽤频率不是很⾼的缓存⻚,所以这⼀部分链表也叫做冷数据,或者称old区域
在这里插入图片描述

young和old可以修改“innodb_old_blocks_pct”进行调整连个区的比例。
mysql>	SHOW	VARIABLES	LIKE	'innodb_old_blocks_pct';
+-----------------------+-------+
|	Variable_name        	|	Value	|
+-----------------------+-------+
|	innodb_old_blocks_pct	|	37   	|
+-----------------------+-------+
1	row	inset	(0.01	sec)

这样修改配置⽂件:
[server]
innodb_old_blocks_pct = 40

为了避免只读取一次的数据,占领了young的数据,所以设计一下模式:
在对某个处在old区域的缓存⻚进⾏第⼀次访问时就在它对应的控制块中记录下来这个访问时间,如果后续的访问时间与第⼀次访问的时间在某个时间间隔内,那么该⻚⾯就不会被从old区域移动到young区域的头部,否则将它移动到young区域的头部。上述的这个间隔时间是由系统变量innodb_old_blocks_time控制的。

mysql>	SHOW	VARIABLES	LIKE	'innodb_old_blocks_time';
+------------------------+-------+
|	Variable_name         	|	Value	|
+------------------------+-------+
|	innodb_old_blocks_time	|	1000 	|
+------------------------+-------+
1	row	inset	(0.01	sec)

更进⼀步优化LRU链表

对于young区域的缓存⻚来说,我们每次访问⼀个缓存⻚就要把它移动到LRU链表的头部,这样开销有点大了,毕竟在young区域的缓存⻚都是热点数据,也就是可能被经常访问的,这样频繁的对LRU链表进⾏节点移动操作是不是不太好啊?是的,为了解决这个问题其实我们还可以提出⼀些优化策略,⽐如只有被访问的缓存⻚位于young区域的1/4的后边,才会被移动到LRU链表头部,这样就可以降低调整LRU链表的频率,从⽽提升性能(也就是说如果某个缓存⻚对应的节点在young区域的1/4中,再次访问该缓存⻚时也不会将其移动到LRU链表头部)

刷新脏页到磁盘

从LRU链表的冷数据中刷新⼀部分⻚⾯到磁盘。
后台线程会定时从LRU链表尾部开始扫描⼀些⻚⾯,扫描的⻚⾯数量可以通过系统变量innodb_lru_scan_depth来指定,如果从⾥边⼉发现脏⻚,会把它们刷
新到磁盘。这种刷新⻚⾯的⽅式被称之为BUF_FLUSH_LRU。
从flush链表中刷新⼀部分⻚⾯到磁盘。
后台线程也会定时从flush链表中刷新⼀部分⻚⾯到磁盘,刷新的速率取决于当时系统是不是很繁忙。这种刷新⻚⾯的⽅式被称之为BUF_FLUSH_LIST。

多个Buffer Pool实例

在多线程环境下,访问Buffer Pool中的各种链表都需要加锁处理啥的,在Buffer Pool特别⼤⽽且多线程并发访问特别⾼的情况下,单⼀的Buffer Pool可能会影响请求的处理速度。所以在Buffer Pool特别⼤的时候,我们可以把它们拆分成若⼲个⼩的Buffer Pool,每个Buffer Pool都称为⼀个实例,它们都是独⽴的,独⽴的去申请内存空间,独⽴的管理各种链表,所以在多线程并发访问时并不会相互影响,从⽽提⾼并发处理能⼒。以在服务器启动的时候通过设置innodb_buffer_pool_instances的值来修改Buffer Pool实例的个数,⽐⽅说这样:
[server]
innodb_buffer_pool_instances = 2
在这里插入图片描述

配置Buffer Pool时的注意事项

  • innodb_buffer_pool_size必须是innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances的倍数(这主要是想保证每⼀个Buffer Pool实例
    中包含的chunk数量相同)。
    假设我们指定的innodb_buffer_pool_chunk_size的值是128M,innodb_buffer_pool_instances的值是16,那么这两个值的乘积就是2G,也就是说
    innodb_buffer_pool_size的值必须是2G或者2G的整数倍。⽐⽅说我们在启动MySQL服务器是这样指定启动参数的:
    mysqld --innodb-buffer-pool-size=8G --innodb-buffer-pool-instances=16
    默认的innodb_buffer_pool_chunk_size值是128M,指定的innodb_buffer_pool_instances的值是16,所以innodb_buffer_pool_size的值必须是2G或者
    2G的整数倍,上边例⼦中指定的innodb_buffer_pool_size的值是8G,符合规定,所以在服务器启动完成之后我们查看⼀下该变量的值就是我们指定的
    8G(8589934592字节):
    mysql>	show	variables	like	'innodb_buffer_pool_size';
    +-------------------------+------------+
    |	Variable_name          	|	Value     	|
    +-------------------------+------------+
    |	innodb_buffer_pool_size	|	8589934592	|
    +-------------------------+------------+
    1	row	inset	(0.00	sec)
    
    如果我们指定的innodb_buffer_pool_size⼤于2G并且不是2G的整数倍,那么服务器会⾃动的把innodb_buffer_pool_size的值调整为2G的整数倍,⽐⽅说
    我们在启动服务器时指定的innodb_buffer_pool_size的值是9G:
    mysqld --innodb-buffer-pool-size=9G --innodb-buffer-pool-instances=16
    那么服务器会⾃动把innodb_buffer_pool_size的值调整为10G(10737418240字节),不信你看:
    mysql>	show	variables	like	'innodb_buffer_pool_size';
    +-------------------------+-------------+
    |	Variable_name          	|	Value      	|
    +-------------------------+-------------+
    |	innodb_buffer_pool_size	|	10737418240	|
    +-------------------------+-------------+
    1	row	inset	(0.01	sec)
    
  • 如果在服务器启动时,innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances的值已经⼤于innodb_buffer_pool_size的值,那么
    innodb_buffer_pool_chunk_size的值会被服务器⾃动设置为innodb_buffer_pool_size/innodb_buffer_pool_instances的值。
    ⽐⽅说我们在启动服务器时指定的innodb_buffer_pool_size的值为2G,innodb_buffer_pool_instances的值为16,innodb_buffer_pool_chunk_size的值
    为256M:
    mysqld --innodb-buffer-pool-size=2G --innodb-buffer-pool-instances=16 --innodb-buffer-pool-chunk-size=256M
    由于256M × 16 = 4G,⽽4G > 2G,所以innodb_buffer_pool_chunk_size值会被服务器改写为
    innodb_buffer_pool_size/innodb_buffer_pool_instances的值,也就是:2G/16 = 128M(134217728字节),不信你看:
mysql>	show	variables	like	'innodb_buffer_pool_size';
+-------------------------+------------+
|	Variable_name          	|	Value     	|
+-------------------------+------------+
|	innodb_buffer_pool_size	|	2147483648	|
+-------------------------+------------+
1	row	inset	(0.01	sec)
mysql>	show	variables	like	'innodb_buffer_pool_chunk_size';
+-------------------------------+-----------+
|	Variable_name                	|	Value    	|
+-------------------------------+-----------+
|	innodb_buffer_pool_chunk_size	|	134217728	|
+-------------------------------+-----------+
1	row	inset	(0.00	sec)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux开发—多进程编程】

【Linux开发—多进程编程】 前言1,两种类型的服务端2,并发服务器的实现方法: 一,认识及应用1,进程认识2,CPU核的个数与进程数3,进程ID4,进程创建5, 调用fork函数后的程序运行流程: 二…

一文了解PWA——Progressive Web App

近年来,出现了一种新的应用开发模式——PWA(Progressive Web App,即渐进式Web应用)。今天就来为大家分享什么是PWA,以及它与小程序的区别、技术原理。 PWA的基本概念和技术原理 PWA是一种基于Web技术的应用开发模式&a…

基于CC2530设计智慧农业控制系统

一、项目背景 智慧农业是近年来发展迅速的领域,其目的是利用先进的传感技术、物联网技术和云计算技术等,实现自动化、智能化的农业生产管理,并提高农业生产效率和质量。本文基于CC2530设计了一种智慧农业控制系统,采用DHT11模块、BH1750模块和土壤湿度传感器等传感器,通过…

turtle和matplotlib画画:圆形、爱心

马上就要到六一儿童节了,小朋友很喜欢画画,这里就用Pyhton来画一些简单形状: 用turtle画圆形 import turtle# 设置画笔颜色和粗细 turtle.pencolor("black") turtle.pensize(5)# 绘制一个半径为100的圆形 turtle.circle(100)# 隐藏…

jsonp的实现原理

什么是跨域: 跨域是浏览器同源策略而产生的,在不同协议,不同端口,不同域名下(以上任意一个不同都算是跨域)的客服端和服务端之间是无法互相访问的。 举例: http://www.baidu.com/index.html …

Springboot +spring security,前后端分离时的security处理方案(一)

一.简介 在前后端分离这样的开发模式下,前后端的交互都是通过 JSON 来进行数据传递的,无论登录成功还是失败,都不会有服务端跳转或者客户端跳转之类的操作。 也就是说无论登录成功还是失败,服务端都会返回一段登录成功或失败的 …

与传统序列化比,PB更快更节省空间

文章目录 为何选择PBPB安装WindowsMac未完待续 语法命令行编译Maven插件编译UDP通信的例子 3大序列化方法对比 为何选择PB 在网络传输和存储数据的时候比传统的 JSON 效果更好 PB安装 GitHub Windows 下载 配置环境变量 验证 Mac未完待续 后续补充Mac安装方式 语法 使用过…

Word、Excel、PPT题库——“办公自动化”

小雅兰期末加油冲冲冲!!! 1.【单选题】下列文件扩展名,不属于Word模板文件的是( A )。 A. .DOCX B. .DOTM C. .DOTX D. .DOT 本题的考查点是word基本知识的了解。 .DOCX:word文档。 .DOTM:启…

目标检测:RPN — Faster R-CNN 的主干

动动发财的小手,点个赞吧! 在使用 R-CNN 的目标检测中,RPN 是真正的主干,并且到目前为止已被证明非常有效。它的目的是提出在特定图像中可识别的多个对象。 这种方法是由 Shaoqing Ren、Kaiming He、Ross Girshick 和 Jian Sun 在…

Pandas 28种常用方法使用总结

Pandas库专为数据分析而设计,它是使Python成为强大而高效的数据分析环境的重要因素。它提供了多种数据结构和方法来处理和分析数据。下面是一些Pandas常用方法的使用总结。 1. 创建数据框 使用read_csv()或read_excel()方法读取数据文件,也可以使用Dat…

饶派杯XCTF车联网安全挑战赛Reverse GotYourKey

文章目录 一.程序逻辑分析二.线程2的operate方法解析三.找出真flag 一.程序逻辑分析 onCreate方法中判断SDK版本是否>27 然后创建两个线程 第一个线程是接受输入的字符串并发送出去 第二个线程用于接受数据 线程1,就是将字符串转为字节数组发送出去 线程2,作为服务端接受…

knife4j、swagger、springdoc 返回接口分组排序问题

一、直击问题 解决前后顺序对比 解决方法: 在配置文件中添加排序规则方法sortTagsAlphabetically: package com.example.demo.config;import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.Security…

OpenMMlab的整体概述和作用

是什么? 开源算法体系(非框架、有开源代码) 用pytorch实现 优势 开箱即用,复现了很多顶会论文中的算法。每个cv任务对应算法库,其中顺序即为学习路线。便于对比实验。 使用统一的框架、超参数,做对比实…

测试接口遇到APP加密?先来了解一下算法思路~

背景 服务端与客户端进行http通讯时,为了防止被爬虫,数据安全性等,引入APP通信加密,简单来说,就是引入签名sign,APP的所有请求都会经过加密签名校验流程。常见的加密方案有AES加密,RSA加密&…

性能测试1

目录 1.什么是性能测试 1.1性能测试的定义 1.2性能测试和功能测试的区别 1.3影响一个软件性能因素有什么影响 2.为什么是性能测试 3.性能测试常见的术语和性能测试衡量指标 3.1并发用户数 3.2响应时间/平均响应时间(RT/ART) 3.3事务响应时间 3.4每秒事务通…

yolov5训练时遇到的问题

torch会自动被requirement.txt替换 在对yolov5_5.0进行pip install requirement.txt后,yolo5_5.0会将虚拟环境中中的torch替换为2.0.1版本的,但要注意查看该torch是否为gpu版本,查看方式如下:打开Anaconda Prompt,激活…

分布式爬虫框架

分布式爬虫框架分为两种:控制模式(左)和自由模式(右): 控制模式中的控制节点是系统实现中的瓶颈,自由模式则面临爬行节点之间的通信处理问题。因此,在实际工程中,我们通常…

go语言命令行工具cobra

go语言命令行工具cobra 1、Cobra 介绍 Cobra 是关于 golang 的一个命令行解析库,用它能够快速创建功能强大的 cli 应用程序和命令行工具。 cobra既是一个用于创建强大现代CLI应用程序的库,也是一个生成应用程序和命令文件的程序。cobra被用在很多 go…

【从球开始渲染小姐姐】DAY1----用blender捏一个小姐姐

Building Blender/Windows - Blender Developer Wikihttps://wiki.blender.org/wiki/Building_Blender/Windows How to build Blender on Windows? - YouTubehttps://www.youtube.com/watch?vb6CtGm4vbng bf-blender - Revision 63388: /trunk/lib/win64_vc15https://svn.b…

DJ4-6 虚拟存储器的基本概念

目录 4.6.1 虚拟存储器的引入 1、常规存储器管理方式的特征 2、内存的扩充方法 4.6.2 局部性原理 4.6.3 虚拟存储器的定义 1、虚拟存储器的基本工作情况 2、虚拟存储器的定义 3、虚拟存储器的实现方法 4.6.4 虚拟存储器的特征 基本分页和基本分段不能解决的问题&a…