自学内容网 自学内容网

MySQL内存(Buffer Pool)

Buffer Pool

MySQL 的数据存在磁盘,但是不能每次读取数据都从磁盘里去,这样磁盘IO太频繁,存在性能问题。
InnoDB设计了一个缓存池(Buffer Pool),缓冲池在内存中。
默认配置Buffer Pool大小为128MB,可以通过innodb_buffer_pool_size参数调整。一般调整为可用物理内存的60%~80%。

Buffer Pool缓存什么?

InnoDB会把存储的数据划分为若干,以页作为磁盘与内存的交互的基本单位,一个页默认大小为16KB,Buffer Pool中也是由构成。
Buffer Pool除了缓存索引页数据页,还包括undo页,插入缓存页、自适应哈希索引、锁信息等等。
在这里插入图片描述

Buffer Pool管理

InnoDB为每个缓存页都创建了一个控制块(类似于文件系统的PCB)

控制块信息包括:缓存页的表空间、页号、缓存页地址、链表节点等等

在这里插入图片描述

空闲页(Free 链表)

为了能够快速找到空闲的缓存页,可以使用链表结构,将空闲缓存页的控制块作为链表的节点,这个链表称为:Free 链表
在这里插入图片描述

脏页(Flush 链表)

与Free 链表类似
在这里插入图片描述

提高缓存命中率

使用简单的LRU算法会导致两个问题:

  • 预读失效
  • Buffer Pool污染

预读失效

  • MySQL有预读机制:
    MySQL在加载数据页时,会提前把它相邻的数据页一并加载进来,目的是较少磁盘IO。原理是程序具有空间局部性。
  • 预读失效:这些被提前加载进来的数据页,并没有被访问,相当于这个预读是白做了。这就是预读失效。
  • 解决:改进LRU算法,将LRU划分为2个区域:old 区 和 young区
    在这里插入图片描述
    预读的数据页放到old区,真正访问的也放到young区。如果预读也一直没被访问,就会从old区域移除。
    young被淘汰的页,会挤到old区的头部。

Buffer Pool 污染

当一个SQL语句扫描大量数据时,会把Buffer Pool的所有数据替换出去,导致大量热数据被淘汰了。
等这些热数据再次被访问时,就没有命中,再次进行磁盘IO,导致性能下降。

解决:
young区里是热数据,提高数据进入young的门槛,可以解决这个问题。
MySQL的解决方法:进入young区条件增加一个停留在old区域的时间判断。 具体如下:

  • 如果后续访问时间与第一次访问时间在某个时间间隔内,该缓存页就不会从old区进入young区。
  • 相反,该缓存页就会移动移动到young区头部。

这个间隔时间有innodb_old_blocks_time控制,默认为1s。

也就是说,只有同时满足[被访问]与 [在old区域停留时间超过1s] 这两个条件,才会被插入到young区头部

MySQL针对young区其实做了一个优化,为了防止young区域节点频繁移动到头部。young区前1/4被方位不会移动到链表头部,只有后3/4被访问才会。

脏页刷新时机

以下几种情况会触发脏页的刷新:

  • 当 redo log 日志满了,会主动触发脏页刷新到磁盘
  • Buffer Pool 空间不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,那么需要先将脏页同步到磁盘。
  • MySQL认为空闲时,后天线程会定期把适量的脏页刷入磁盘
  • MySQL正常关闭之前,会把所有脏页刷入到磁盘。

总结

在这里插入图片描述


原文地址:https://blog.csdn.net/ansizy/article/details/142378238

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!