图解MySQL系列-Buffer Pool中的free链表
Posted JavaEdge.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图解MySQL系列-Buffer Pool中的free链表相关的知识,希望对你有一定的参考价值。
1 mysql如何初始化Buffer Pool
Buffer Pool中有N多缓存页,每个缓存页还有个描述信息。DB启动后,按BP大小向os申请一块内存区域,作为BP的内存区域。
当内存区域申请完后,DB按默认缓存页及对应描述信息快,在BP中划出一块块内存,当DB把BP划分完后:
这时,BP中的一个个缓存页还都是空的,要等DB运行起来后,当我们要对数据执行CRUD操作时,才会把数据对应的页从磁盘文件里读取出来,放入BP中的缓存页。
哪些缓存页空闲?
DB运行后,肯定执行大量CRUD,就需不停的从磁盘上读取一个个数据页放入BP中的对应的缓存页里去,把数据缓存起来,后续就能对该数据在内存里执行CRUD。
但是此时在从磁盘上读取数据页放入Buffer Pool中的缓存页的时候,必然涉及到一个问题,那就是哪些缓存页是空闲的?
因为默认情况下磁盘上的数据页和缓存页一一对应,都是16K,一个数据页对应一个缓存页。所以必须要知道BP中哪些缓存页是空闲状态。
所以数据库会为BP设计个free链表,双向链表,每个节点就是个空闲缓存页的描述数据块的地址,即只要一个缓存页空闲,那他的描述数据块就会被放入free链表。
刚开始DB启动时,可能所有缓存页都空闲,因为此时可能是个空DB,所以此时所有缓存页的描述数据块,都放入free链表。
上图中,这free链表里就是各个缓存页的描述信息块,只要缓存页空闲,对应的描述信息块就会加入free链表,每个节点都会双向链接自己的前后节点,组成一个双向链表。free链表有个基础节点引用链表的头节点和尾节点,存储了链表中有多少个描述数据块的节点,即有多少个空闲缓存页。
free链表占用内存大小
这free链表本就由BP里的描述信息块组成,可认为是每个描述信息块里都有两个指针:
-
free_pre
指向自己的上一个free链表的节点
-
free_next
指向下一个free链表的节点
通过BP中的描述数据块的free_pre和free_next两个指针,就能将所有描述数据块串成一个free链表,上面只是为了方便画图,所以将描述信息块单独画出来。
对free链表,只有一个**基础节点(40K)**不属于BP,存放了free链表的头节点地址,尾节点地址,还有free链表当前节点个数。
如何将磁盘上的页读取到BP的缓存页?
先从free链表获取一个描述信息块,就能获取到对应空闲缓存页。
就能将磁盘上的数据页读到对应缓存页,同时将相关的描述信息写入缓存页的描述信息块,比如该数据页所属的表空间之类的信息,最后把那描述信息块从free链表中移除:
怎知数据页是否被缓存?
执行CRUD时,先看该数据页是否被缓存,若没被缓存就走上面逻辑,从free找个空闲缓存页,从磁盘上读取数据页写入缓存页,写入描述信息,最后从free中移除该描述信息块。
但若数据页已被缓存,就能直接使用。
所以DB还有个数据页缓存哈希表:
- key:表空间号+数据页号
- value:缓存页的地址
当要使用一个数据页时,通过“表空间号+数据页号”作为K查这个哈希表:
- 若无,读取数据页
- 若有,说明数据页已被缓存
每次读取一个数据页到缓存后,都会在这哈希表写入一个数据,下次若再使用这数据页,就能从哈希表直接读出来,毕竟他经被放入一个缓存页了:
以上是关于图解MySQL系列-Buffer Pool中的free链表的主要内容,如果未能解决你的问题,请参考以下文章
大白话系列MySQL 学习总结 之 缓冲池(Buffer Pool) 如何支撑高并发和动态调整