首页 > 其他分享 >细说InnoDB缓冲池 buffer pool(free、flush、lru)

细说InnoDB缓冲池 buffer pool(free、flush、lru)

时间:2022-10-24 20:56:23浏览次数:97  
标签:缓存 buffer free 链表 InnoDB flush 数据

细说InnoDB缓冲池 buffer pool(free、flush、lru)  2021-12-12 21:57:42     小道仙     126阅读     2评论

视频地址 https://www.bilibili.com/video/BV1C3411t7WL

 

Table of Contents

 

一、开篇

在InnoDB引擎中对数据库增删改查,都是先从磁盘中把数据加载到内存,然后在内存中进行相关操作,我们把这块的内存称之为 buffer pool (缓冲池)

既然这是内存中的一块区域,那么它就一定有大小(默认是128M),如果你有一个16G的数据库服务器,你安装好MySQL,那你的缓冲池的大小就是128M,这时候肯定很影响你的操作,因为它太小了,所以我们应该根据当前条件来对这个参数进行修改:innodb_buffer_pool_size

说到数据库,大家脑海里肯定是库、表、行、字段,这其实没错毕竟我们对它就是这样操作的,这其实也错,因为我们知道数据是存在硬盘中的,硬盘怎么会有这些个逻辑数据呢?肯定是都存储的物理数据。

在硬盘中,MySQL把16KB作为一个单位,我们把这个叫做数据页,一页里面可以存储很多的数据,页之间是有双向指针进行关联的。

从硬盘中读取数据到缓冲池也是以页为单位的,在缓冲池中有一个叫做缓存页的东西,它也是16KB大小,每读取一个数据页就把它放在一个空闲的缓存页里面。

除了这个缓存页之外还有一个叫做元数据的东西,你可以这样理解这个每个元数据和每个缓存页一一对应,它相当于是缓存页的头,它里面存储了缓存页的基础信息,下面你就会明白它的作用了。

好了,到这里我们就知道了buffer pool里面有缓存页(16KB),元数据,那么你的脑海里应该浮现这样的图

image.png

buffer pool默认的大小128M,是用来存储数据的,也就是缓存页,但同时也还要存储元数据,所以实际上它的大小会比128M要大一些。


二、free链表

上面说到,我们是把硬盘中的数据页一片片加载到buffer pool的缓存页里面去,那这里就存在一个问题:怎么知道哪些数据页是空的呢?我们不可能去覆盖别的数据对不对?

其实这里维护了一个free链表,它是由空闲的元数据组成的(前面我们说了这个元数据和缓存页是一一对应的,所以一个空闲元数据就对应一个空缓存页),这样我们就很容易的知道那些缓存页是空的、还有多少空的缓存页。

image.png

这个基本结点是单独的空间,它里面就存储了链表长度等其它的数据。

如果有新的数据页要加载到缓存中,就从free链表里面取出一个元数据找到对应的缓存页,然后放进去,在把这个元数据从free链表里面剔除。

可以理解成你在Java中的链表,伪代码实现 head.next = head.next.next


三、flush 链表

上面的free链表是标示空闲的缓存页,而我们的修改数据也是在缓存页里面操作的,这些数据并未存储到磁盘中去,毫无疑问肯定是要记录哪些缓存页是已经修改了的,不然系统怎么把它们刷进磁盘呢?而这个记录的地方也就是 flush链表

flush链表也是和上面free链表一样:基于元数据组成的。当有一个缓存页被修改之后就把它加入到flush链表里面去。

注:可能有人有疑问为啥这个元数据可以组成free链表又能组成flush链表呢?其实熟悉链表结构的朋友都知道,链表只是一个指向的问题而已,我们可以在元数据里面定义N个,next、front,指针去指向就好了。

因为flush链表和free链表结构基本上是一样的,所以就不花了,但是要理解不是单独的两个链表,而是两种指向。

有了flush链表,当要把数据刷回磁盘的时候就容易多了,具体何时刷入下面再说。


四、LRU 链表

这里我们还有一个问题,我们的数据都是存储在缓存中的,而缓存大小是有限的,有些数据很可能就是查询一次就不再使用了,如果让它一直存储在缓存中那肯定是不合适的。所以这里我们引入一个新的链表 LRU链表 (Least Recently Used)最近最少使用的意思,也就是我们可以使用这个链表来维护热点和非热点数据。

注:这个链表的节点也是基于元数据来组成的,但是和上述两个链表还是有些差异。

何为热点数据,这其实是一个定义问题。当然按照顺序排序把最近访问的数据放到链表头部,那这样的话前面的数据就是热点数据。

但是MySQL有两个操作会让上面这种方式产生漏洞,全表扫描预读


全表扫描

这很好理解,比如你写一个不带任何条件的查询SQL: SELECT * FTOM t_user,这会加载很多的数据页到缓存中,但实际上很多数据只用一次就不再使用了。


预读

在InnoDB引擎下,当你一次读取超过56页数据的时候就会触发预读,也就是在InnoDB看来,如果你一下次读取了56页数据,那么你大概率也是要读取57、58…

这个56是来自默认的配置,当然你页可以修改它的配置文件 innodb_read_ahead_threshold


冷热区域

为了解决上面的这个“漏洞”,真实的LRU链表是分冷热区域的,当数据页从磁盘加载到内存的时候,会把它放在冷区域的头部,当超过1s后再次去访问这个数据的时候才会把它移动到热区域。

  • innodb_old_blocks_pct 冷区域的大小默认是 37%
  • innodb_old_blocks_time 多少毫秒之后访问冷数据,会加载到热区域 默认 1000

按照我们的理解如果超过1s后再访问冷区域的数据就把它移动到热区域,这个是没问题的。

但如果我们访问热区域的数据,是不是每次访问就把它移动到热区域的头部呢?这样看似合理,实则不合理,你想想频繁的移动也是需要消耗性能的,所以只有在访问热区域的后75%的数据才会移动到热区域的头部。

image.png


五、数据回盘

buffer pool是内存的一块区域,它总会有满的时候,如果它满了那怎么办呢?其实通过上面的几个链表我们已经知道了,如果满了,可以把LRU链表的冷区域的数据进行刷回磁盘操作就好了。

另外一个问题就是flush链表里面的脏页何时被刷回磁盘呢?它有两个操作,一个是上面的磁盘空间不足的时候会把LRU链表里面的冷数据刷回磁盘,这里面也包含了一些flush链表里面的数据,一个是后台有一个IO线程会不定期的把flush链表里面的脏页刷回磁盘。

注:free、flush、lru 都是指的相同的数据,只不过是按照不同的指向组成了不同的链表而已。

  转载:https://www.xdx97.com/article/919709627669544960

标签:缓存,buffer,free,链表,InnoDB,flush,数据
From: https://www.cnblogs.com/wugh8726254/p/16822756.html

相关文章

  • mysql InnoDB建表时设定初始大小的方法
    InnoDB在写密集的压力时,由于B-Tree扩展,因而也会带来数据文件的扩展,然而,InnoDB数据文件扩展需要使用mutex保护数据文件,这就会导致波动。丁奇的博客说明了这个问题:WhenInno......
  • Mysql索引原理揭秘之——MyISAM和InnoDB
    MyISAM引擎的索引实现在MyISAM里面,另外有两个文件,一个是.MYD文件,D代表Data,是MyISAM的数据文件,存放数据记录,比如我们的user_myisam表的所有的表数据;一个是.MYI文件,I代表Inde......
  • FreeCAD的编译
    一、获取源码https://github.com/ninuo/FreeCAD通过git下载源码gitclonehttps://github.com/ninuo/FreeCAD.git二、下载依赖包LibPack-0.19通过https://githu......
  • unity 使用Cinemachine的FreeLook相机实现第三人称视角及鼠标滑轮远近镜头效果
    安装Cinemachine如果你没有安装过Cinamachine,则需要在包管理器中选择Uinty注册表搜索Cinemachine进行安装 打开位置Cinemachine 调整相机设置①设置相机注视跟......
  • FreeAC
    FreeAChttps://www.right.com.cn/forum/thread-180295-1-1.htmlhttps://gitee.com/freeac/FreeAChttps://github.com/ycsunjane/acctlhttps://github.com/hokamyuen/op......
  • #yyds干货盘点#Arraybuffer转String
    ​​ArrayBuffer​​ 对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(​​TypedArray​​视图和​​DataView​​视图)来读写,视图的作用是以指定格式解读二进......
  • PG如何进行vacuum freeze
    vacuumfree能有效将事务年龄过大的问题解决,但是这个非常耗时间,这个时候最方便的就是开启screen进行vacuumfreeze开启screen窗口$screen-dmSyour_session_name#your......
  • StringBuffer、StringBuilder、String 区别
    String字符串常量不可变使用字符串拼接时是不同的2个空间StringBuffer字符串变量可变线程安全字符串拼接直接在字符串后追加StringBuilder字符串变量可变非线程安......
  • Lock Free 之 Epoch Based Reclamation
    EpochBasedReclamation  EpochBasedReclamationepochbasedreclamation 算法参考文档:http://www.cs.toronto.edu/~tomhart/papers/tomhart_thesis.pdfhttps:......
  • freeswitch隐藏fs标识
      概述freeswitch是一款好用的开源软交换平台。fs的默认配置环境下,sip消息中有很多freeswitch的标识,比如“user-agent”,“contact”头域等等。对于某些场景,我们希......