Mysql中的BufferPool

为什么会产生buffer pool:

Innodb存储引擎设计了一个缓冲池,来提高数据库的读写性能

没有缓冲池前,读写数据要直接对磁盘上的数据进行操作,磁盘的读取速度很慢,会影响到数据库的读写速度

有了缓冲池后:

当读取数据时,如果数据在缓冲池中,客户端会直接读取缓冲池中的数据,否则再去磁盘读取

当修改数据时,首先是修改缓冲池中的数据所在页,然后将其页设置为脏页,最后由后台线程将脏页写入磁盘中

buffer pool多大:

buffer pool 是在MySQL启动的时候,向操作系统申请的一片连续的内存空间,默认配置下buffer pool只有128MB

可以通过调整innodb_buffer_pool_size参数来设置buffer pool的大小,一般建议设置成可用物理内存的60%~80%

buffer pool缓存的是什么:

Innodb会把存储的数据划分为若干个页,以页作为磁盘和内存交互的基本单位,一个页的默认大小为16kb,因此,buffer pool同样需要按页来划分

为了管理这些在buffer pool中的缓存页,InnoDB为每一个缓存页都创建了一个控制块。

控制块也是占有内存空间的,它是放在buffer pool的最前面,接着才是缓存页

上图中位于控制块和缓存页中间的灰色部分称为碎片空间

形成原因,该段内存空间不足以放下一个控制块和一个缓存页,从而形成了碎片空间

管理buffer pool中的数据页

buffer pool中的数据页可以分为三种,脏页,干净页,空闲页

每个页面所要进行的操作

脏页是修改过数据的页面,在写入磁盘后会变成干净页,脏页也可以被再次命中

干净页是从磁盘中缓存来没有被更改的数据(或者没有被使用的数据页),需要后续被使用或者被替换掉

空闲页就是没有数据的空白页,当还要从磁盘读取数据时,会先写入到该页中

对三种页面进行处理,前提是要找到它们,而脏页和空闲页没有特异性,所有找到即可,不用管是那个

而干净页因为要用到里面的数据,所以有特异性,所以要进行准确的查找

如何管理空闲页

buffer pool是一片连续的内存空间,当mysql运行一段时间后, 这片连续的空间中的缓存既有空闲的,也有被使用的,为了减少找到空闲页的时间,可以使用链表将所有的空闲页连接起来,称为free链表(空闲链表)

链表头节点的,包含了该链表的头节点的地址,尾节点的位置,和链表的节点数量。

有了free链表后,每当需要将磁盘中的数据读到空闲页中,直接从free链表中取一个空闲的缓存页即可,然后把该缓存页对应的控制块的信息填上,然后把该缓存页对应的控制块从free链表中删除

如何管理脏页

设计buffer pool除了能提高读性能,还能提高写性能,也就是更新数据的时候,不需要每次都要写入磁盘,而是将

该数据页标记为脏页,然后通过异步的方式,就是交给后台线程将脏页写入到磁盘中

跟寻找空闲页一样,如果顺序查找所有页,太浪费时间,所有也使用链表将所有脏页连接起来,称之为Flush链表其结构跟free链表一样

有了 Flush 链表后,后台线程就可以遍历 Flush 链表,将脏页写入到磁盘

管理干净页

buffer pool 的大小是有限的,所以要尽量使装入数据,都是要使用的数据,即提高缓存的命中率

当缓存池满了的话,会将部分不常用的数据淘汰掉

该方法的实现思路是使用LRU算法

该算法的思路是,链表头部的节点是最近使用的,而链表末尾的节点是最久没被使用的。那么,当空间不够了,就淘汰最久没被使用的节点,从而腾出空间。

形成一个 LRU 链表,但是该链表中既有干净页也有脏页

简单的LRU算会导致两个问题

预读失效

mysql有预读机制,是为了适应程序的空间局部性,就是靠近当前被访问数据的数据,在未来很大概率会被访问到

所以MySQL在加载数据时,会提前把它相邻的数据页一并加载出来,目的是为了减少磁盘IO。

但是如果使用简单的LRU算法,就会把预读页放到链表的头部,而当bufferpool空间不够时,就会把尾部的页淘汰掉,但是预读页不一定会被使用,这样就会导致一个问题,就是一直不被使用的页却占据链表的头部,真正被使用的页却在链表尾部,这样就会大大降低缓存的命中率

不妨去掉预读机制,但是预读机制在大部分时候还是成立的,所以不用该直接除去预读机制,然是采取优化LRU算法的方式,去解决预读失效的问题,就是将一个链表分为两段,预读的数据加到一个区域,被访问的页加到另一个区域,每个区域都有自己的头节点可以直接访问到

什么是bufferpool污染

当某个sql语句扫描了当量数据时,在buffer pool空间比较有限的情况下,可能会将bufferpool里的所有页都替换出去,导致大量热数据被淘汰,当这些热数据又被访问的时候,由于缓存未命中,就会产生大量的磁盘IO,mysql性能就会急剧下降,这个过程就被称为bufferpool污染,例如全表扫描的时候,会导致大量数据被加入到,但是这些数据大概率就都不会被命中,从而导致大量有用的数据被淘汰掉,进而降低了缓存命中率

暂时没有理解透,所以不讲

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值