MySQL内存篇

为什么要有Buffer Pool?

  • 数据库中的数据是存储在磁盘中的,如果每次我们进行数据库的读写操作都去磁盘中查找和修改,因为涉及到磁盘的IO,读写的性能就会比较低。
  • MySQL则通过一个缓冲池来存储哪些最常用的数据页(我们叫做缓存页),我们在进行数据库的读写操作时,先去缓冲池中找,如果有则不需要去磁盘中查找,从而提高了数据库的读写性能

Buffer Pool缓存什么?

  • 实际上,Buffer Pool中存储的不仅有数据页,还有索引页、插入缓存页、undo页等

  • 为了更好地管理这些缓存页,每一个缓冲页都对应了一个控制块,它记录了缓存页的表空间、页号、地址、链表节点等信息。

  • 需要注意的是,并不是查询一条记录就缓冲一条记录,实际上,数据库通过索引只能查询到记录所在的数据页,同时,如果存在预读机制,还会将相邻的数据页一起加载到缓冲池中,之后,再通过数据页里的页目录去定位到某条具体的记录

如何管理Buffer Pool?

Buffe Pool中的缓存页分为三种:空闲页、干净页还有脏页

  • 空闲页:没有被使用的页
  • 干净页:被使用,但是没有被修改的页
  • 脏页:被使用,也被修改的页

为了管理这些数据页,MySQL通过三个链表来管理:

  1. Free链表维护空闲页

链表节点包含了空闲页对应的控制块地址,控制块又知道这些空闲页的地址,从而通过链表将这些空闲页维护在一起

  1. Flush链表维护脏页

和Free链表结构一样,只是维护的缓存页类型不同

  1. LRU链表维护干净页和脏页


为了提高数据库缓存的命中率,我们需要将哪些不经常被使用的数据页换出,最容易想到的实现算法就是LRU
但是,LRU会带来两个问题

普通的LRU算法维护LRU链表会带来的缓存命中率下降

  1. 预读失效:提前加载进来的数据页,没有被访问

由于局部性原理,也就是当我们访问一个数据页时,其相邻的数据页也很大概率会被访问到(也可能不会被访问)
因此,MySQL在加载数据页时,会将其相邻的数据页一起加载进Buffer Pool中,那么这些被提前加载进来的数据页就会被加入LRU链表的头节点,但是,如果这些被提前加载进来的数据页一直没被访问,反而因为占用链表头部区域,会将LRU链表中那些热点数据页淘汰,从而使得缓存命中率大大下降

  • 如何解决预读失效导致的缓存命中率下降?

预读可能会失效,但是我们不能因为少部分情况下的预读失效(大部分情况下,局部性原理还是成立的)
为了解决这个问题,就是要让预读页在Buffer Pool的停留时间尽可能地短,让真正被访问的页才能移动到链表的头部,从而保证热数据在Buffer Pool中停留的时间尽可能长
MySQL将LRU链表分为young和old两个区域,young区域在链表头,old区域(默认占37%)在链表尾

我们将预读页插入到old区域的头部,将真正要读取的页插入到young区域,old区域中的预读页只有在被使用的时候,才会被移动到young区域头部,而如果old区域的预读页一直没有被访问,就会因为新的预读页插入而被淘汰

  1. Buffer Pool污染:一个SQL语句扫描了大量数据,从而使得Buffer Pool中所有页被替换出去,导致大量热数据被淘汰

想象执行下面的一条索引失效的查询语句:

select * from t_user where name like "%xiaolin%";

索引失效,导致全表扫描,磁盘读取到的数据页插入LRU链表的old区域,扫描数据页中记录的过程中由于数据页被使用,会被移动到young区域头部,数据量很大时,很有可能就会将Buffer Pool中的所有缓存页替换

为了解决Buffer Pool污染导致的缓存命中率下降,需要提供old区域的数据页进入young区域的门槛,不仅要被使用,还要满足在old区域中停留时间超过1s(默认)

  • 另外,为了防止young区域节点频繁移动到链表头部,young区域前面1/4被访问不会被移动到链表头部

脏页刷新时机

  1. redo log是物理日志,记录的是某个数据页做了什么修改,对应了脏页,所以如果redo log满了,则会刷新脏页
  2. Buffer Pool空间不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,则需要将脏页刷盘
  3. MySQL认为空闲时,后台线程会将脏页刷盘
  4. MySQL正常关闭之前,会将脏页刷盘
  • 脏页刷盘会给数据库带来性能开销,会导致数据库操作抖动具体表现在慢SQL监控开启时会发现一些耗时较长的SQL操作,如果间断出现这种情况,就需要考虑调大Buffer Pool空间或redo log日志大小
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值