Mysql内存组件Buffer-Pool分析(3)

·  阅读 307

其实mysql为什么设计预读机制只不过是优化性能嘛。现在假设你访问了顺序访问了1-56的数据页。那么mysql会觉得你还会访问第60个数据页。它当然会把后面一个数据区的数据页加载到buffer-pool中了。那这个时候你再访问第60个数据页的时候是不是就可以在缓冲区(buffer-pool)中执行获取了性能就提高了。

基于冷热数据分离思想设计LRU链表

之所以我们之前简单的LRU链表会有问题其根本就是把冷热数据混在了一起,那现在我们将冷热数据分开。我通过配置innodb_old_blocks_pct 参数来控制它的默认值是37. 意思是冷数据占比37%。

那么我们数据第一次被加载到buffer-pool的时候在什么位置呀? 其实就是在冷数据区域的头部。那我们冷数据什么时候被让到热数据里面去呀?就是在数据被加载到冷数据区域1秒内被访问使用那它就会放到热数据的头部。我们可以通过配置innodb_old_blocks_time 默认是1000 就是我们上面的1秒,我们也可以修改。 那我们来想一下那对于mysql预读机制带来的问题解决了吗?大家看着图想一下。 一下子加载进来的预读数据是不是都在冷数据区域,那它要今日热数据区域必须在1秒内被访问。所以我们的LRU链表热数据区域保存的就是经常被使用和访问的数据。而冷数据区域保存的就是不需要关注的缓存页那当我们Free链表不够需要淘汰掉一些缓存页的时候,直接去冷数据区域找到尾节点开始淘汰。

优化热数据区域

对于热数据区域我是不是一旦某个缓存被使用就移动到头部我想是不应该这样的。 因为我们的热数据区域是经常被访问的经常移动链表节点是不合适的。 所以我们对于热数据区域后四分之三的区域被访问才会被移动到前面去。 对于前四分之一的区域被使用到了是不会移动的。举个例子假设我们的LRU链表热数据区域有100个节点。 那前25个节点缓存页被使用到了是不会移动的,只有后75个缓存页被使用到了才会移动到前面去。 这样可以尽可能的减少链表节点的移动。

我们回忆一下当缓存页加载了数据到buffer-pool的时候首先Free链表会移除这个缓存页,因为free保存的是空闲的缓存页也就是没有加载数据的缓存页。其次是flush链表会记录这个“脏页” 然后LRU会将你加入到冷数据区域如果你在1秒内被访问了缓存页会进入到热数据区域。总之我们Mysql在进行CRUD的时候需要不停的操作这几个链表。 那什么时候缓存页里的数据被刷入到磁盘?

  1. 定时刷入磁盘文件(如上图)其实并不是一定要等到没有空闲的缓存页可以用了我们才会将缓存页刷入磁盘文件。它会运行一个定时任务去每隔一段时间就会将冷数据区域里的缓存页刷入磁盘。然后将这些缓存页重新加入到Free链表里,从flush链表中移除,从LRU链表移除。
  2. 没有空间了将缓存页刷入磁盘。如果只需要一个数据页加载到buffer-pool中那一定会去LRU链表中冷数据区域找到一个节点将那个缓存页刷入到磁盘。然后free链表有一个节点空闲。lru链表、flush链表里移除。

到这里我们分享了mysql内存组件buffer-pool,我们在CRUD的时候是如何基于内存组件进行的。已经三个链表是如何配合的。

分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改