mysql Buffer Pool——缓冲池

什么是buffer pool

在这里插入图片描述

  1. 是一块连续的内存空间,当数据库操作数据的时候,把硬盘上的数据加载到buffer pool,不直接和硬盘打交道,操作的是buffer pool里面的数据
  2. 控制块占缓冲页百分之5左右的内存大小,控制和缓冲页是一一对应的关系
  3. 默认大小 128M
  4. 数据库只要一启动,就会按照你设置的Buffer Pool大小,稍微再加大一点,去找操作系统申请一块内存区域,作为Buffer Pool的内存区域

控制块

  1. 存的是 数据页所属的表 空间号,数据页编号,数据页地址等信息
  2. 是放在缓存页的前面
  3. 控制块占缓冲页百分之5左右的内存大小

缓存页

  1. buffer pool中存放的数据页我们叫缓存页,和磁盘上的数据页是一一对应的,都是16KB
  2. 缓存页的数据,是从磁盘上加载到buffer pool当中的

buffer pool缓存什么?有什么用?

缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘IO,起到加速访问的作用。

free链表

在这里插入图片描述

  1. 作用:帮助我们找到空闲的缓冲页
  2. 是一个双向链表,链表节点是空闲的缓存页对应的控制块(空的缓冲页)
  3. 链表上除了控制块,还有一个基节点,存储了free链有多少个控制块,也就是有多少个空闲的缓冲页
  4. 基节点的start指向链表的头结点,end指向链表的尾节点
  5. 当我们加载数据的时候,会从free链中找到空闲的缓冲页,把数据页的表空间号和数据页号写入控制块;加载数据到缓冲页后,会把缓冲页对应的控制块从free链表中移除

怎么知道数据页是否被缓存?

  1. 通过hash表,key对应的表空间+页号。value对应的缓冲页的控制块
  2. 这样就可以通过表空间+页号找到控制块,然后通过控制块找到缓冲页了

flush链表

在这里插入图片描述

  1. 是一个双向链表,链表结点是被修改过的缓存页的描述信息块(更新过的缓存页)
  2. 作用:帮我们找到脏缓存页,也就是需要刷盘的缓存页
  3. 和free链表一样,也有一个基节点,链接首尾结点。
  4. 存储了有多少个控制块,就有多少个脏页。

什么是脏页

  1. 当进行了增删改查导致buff pool里面的缓冲页的数据与磁盘上的数据不一致的时候,这样的缓冲页被称之为脏缓冲页(脏页)
  2. 这种脏页是要被刷到磁盘上去的

flush链表如何进行刷盘操作

有两种方式

  1. 从flush链表中刷新一部分缓冲页到磁盘,定时:根据业务的繁忙程度定时的把脏页刷到磁盘上去,在负载很高的时候,脏页的刷盘操作会比较慢,buff pool里面没有可用的空闲缓冲页了。会从lru列表尾部开始检查看,找到一个脏页把它刷到磁盘上去
  2. 从LRU链表的冷数据区中刷新一部分刷到磁盘,定时的执行。

LRU链表

在这里插入图片描述

  1. 是一个双向链表,链表结点是 非空的缓冲页对应的控制块(有数据的缓存页,包含更新过和未更新过的缓存页,范围比flush链表大)
  2. 作用:用来淘汰不常被访问的缓存页
  3. LRU链表分为热数据区和冷数据区,冷数据区占了总链表的37%。冷数据区是不常访问的缓存页,热数据区是经常访问的缓存页。

什么是预读

在mysql 读取磁盘的时候不是一条一条的读取数据,而是按照页(16kb)一页一页的去读取数据,在还没有读取到这个页的数据的时候就把该页读取到buff pool里面这就叫预读。
基于这种预读有两种判断

  1. 线性预读:就是按照顺序的访问某一个区,连续顺序访问区(区默认包含64个页)中56个页之后会把当前区当做一个热点区,会异步的加载下一个区全部的页到buff pool
  2. 随机预读:默认不开启,开启之后。只要一个区当中只要有连着的13个页被访问之后,该区的所有页会被加载到buff pool里面去

什么是预读失效?

由于预读,会把数据页提前加载到buff pool里面去当,但是mysql时最终没有被使用。被称之为预读失效

如何解决的呢

1.将LRU分为两个部分:

  1. 新生代(热数据区)(new sublist)
  2. 老生代(冷数据区)(old sublist)

2.新老生代收尾相连,即:新生代的尾(tail)连接着老生代的头(head);

3.新页(例如被预读的页)加入缓冲池时,只加入到老生代头部:

  1. 如果数据真正被读取(预读成功),才会加入到新生代的头部
  2. 如果数据没有被读取,则会比新生代里的“热数据页”更早被淘汰出缓冲池

什么是MySQL缓冲池污染?

当执行某条sql语句,需要扫描大量的数据的时候。会把buff pool大面积的替换掉,导致热数据被替换掉。从而导致mysql的性能急剧下减,这叫mysql缓存池污染。
例如,有一个数据量较大的用户表,当执行:select * from user where name like “%shenjian%”;虽然结果集可能只有少量数据,但这类like不能命中索引,必须全表扫描,就需要访问大量的页

如何解决的呢

MySQL缓冲池加入了一个“老生代停留时间窗口”的机制:

  1. 假设T=老生代停留时间窗口;
  2. 插入老生代头部的页,即使立刻被访问,并不会立刻放入新生代头部;
  3. 只有满足“被访问”并且“在老生代停留时间”大于T,才会被放入新生代头部;

参数

innodb_buffer_pool_size

配置缓冲池的大小,在内存允许的情况下,DBA往往会建议调大这个参数,越多数据和索引放到内存里,数据库的性能会越好。

innodb_old_blocks_pct

生代占整个LRU链长度的比例,默认是37,即整个LRU中新生代与老生代长度比例是63:37。如果把这个参数设为100,就退化为普通LRU了。

innodb_old_blocks_time

老生代停留时间窗口,单位是毫秒,默认是1000,即同时满足“被访问”与“在老生代停留时间超过1秒”两个条件,才会被插入到新生代头部。

总结

(1)缓冲池(buffer pool)是一种常见的降低磁盘访问的机制;

(2)缓冲池通常以页(page)为单位缓存数据;

(3)缓冲池的常见管理算法是LRU,memcache,OS,InnoDB都使用了这种算法;

(4)InnoDB对普通LRU进行了优化:

将缓冲池分为老生代和新生代,入缓冲池的页,优先进入老生代,页被访问,才进入新生代,以解决预读失效的问题

页被访问,且在老生代停留时间超过配置阈值的,才进入新生代,以解决批量数据访问,大量热数据淘汰的问题

https://blog.csdn.net/wuhenyouyuyouyu/article/details/93377605 参考了一下文章

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值