mysql-buffer缓冲区+链表

目录

数据页溢出

数据页缓存哈希表

缓存页结构

free链表基础节点

free链表

Buffer Pool

描述数据

flush基础节点

 flush链表

 LRU链表

预读机制

innodb_read_ahead_threshold

innodb_random_read_ahead

全表扫描

LRU优化

1. 冷热数据区域

2. 定时把LRU尾部缓存页刷入磁盘

3. 空闲时间把flush链表中的数据刷入磁盘

设置多个buffer pool并发操作

 chunk

查看系统配置


  

数据页溢出

第一个数据页会存储部分数据,数据最后包含一个20个字节的指针,指向了其他的一些数据页,那些数据页用链表串联起来

  

数据页缓存哈希表

插入数据的时候,先从磁盘中加载一个空的数据页,添加到缓存页,然后将数据写到缓存页中

保存缓冲区中所有的位置(表空间号+数据页号),在对数据进行操作的时候,会先去 缓存哈希表 查找数据存放的数据页是否存在,存在的话,拿到 缓存哈希表 key 对应的 缓存页地址去获取数据,不存在从磁盘获取数据页,从free链表获取空闲缓冲页,读取的数据写入到缓冲区,缓冲区地址保存到 哈希表

  

缓存页结构

free链表基础节点

他是40字节大小的一个节点,里面就存放了free链表的头节点的地址,尾节点的地址,还有free链表里当前有多少个节点

free链表

他本身其实就是由Buffer Pool里的描述数据块组成的,你可以认为是每个描述数据 块里都有两个指针,一个是free_pre,一个是free_next,分别指向自己的上一个free链表的节点,以及下一个free链表的节点。

Buffer Pool

一般来说bufferPool的总大小为 服务器内存大小的50%-60%
buffer pool总大小=(chunk大小 * buffer pool数量)的倍数
Buffer Pool中的描述数据大概相当于缓存页大小的5%左右,也就是每个描述数据大概是800个字节左右的大小,然后假设你设置的buffer pool大小是128MB,实际上Buffer Pool真正的最终大小会超出一些,可能有个130多MB的样子,因为他里面还要存放每个缓存页的描述数据

描述数据

该数据页所属的表空间、数据页的编号、这个缓存页在Buffer Pool中的地址以及别的一些杂七杂八的东西 

flush基础节点

 flush链表

对内存中的缓冲页作出了修改,那该缓冲页对应的描述信息块就会添加进 Flush List。这样当Buffer Pool中的数据页不够用时,我们就可以优先将 Flush List中的脏数据页刷新进磁盘中。

 LRU链表

当free链表为空的时候,说明缓冲区中的缓存页都被使用,这个时候,新的数据操作进来,需要淘汰一个缓存页,这个时候,淘汰LRU链表的最后一个节点,将节点加入到free链表(为了好理解说为将腾出来的缓存页对应的描述数据放到free链表,实际 不管是 free 链表,flush链表,LRU链表 都是在一个节点,节点内的属性值会标记各个链表的 上一个节点 和 下一个节点)

预读机制

预读会导致,LRU链表中前面的数据都是新添加的数据,经常被访问的一些数据会被放到尾节点,再有新数据添加的时候这些经常被访问的数据会被淘汰掉

innodb_read_ahead_threshold

默认值是56,意思就是如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,此时就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去 

innodb_random_read_ahead

 Buffer Pool里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去这个机制是通过参数innodb_random_read_ahead来控制的,他默认是OFF,也就是这个规则是关闭的

全表扫描

全表扫描会导致他直接一下子把这个表里所有的数据页,都从磁盘加载到Buffer Pool里去。这个时候他可能会一下子就把这个表的所有数据页都一一装入各个缓存页里去!此时可能LRU链表中排在前面的一大串缓存页,都是全表扫描加载进来的缓存页

LRU优化

1. 冷热数据区域

为了解决预读机制造成的问题,将 LRU 链表分为两部分

冷数据区域,默认占缓存区的37%,innodb_old_blocks_pct 控制

当全表扫描或者预读机制,加载的数据页,会被先加载到冷数据区域的头部,如果冷数据区域的缓存页在1s后被再次访问,会被放到热数据区域的头部,当有数据要淘汰的时候,直接淘汰冷数据区域最后的 缓存页节点。

热数据区域的数据是经常被访问到的,这个时候热数据区域的数据节点会被频繁的移动,造成系统性能的浪费,mysql 将 热数据区域划分为,固定区(前1/4),移动区(后3/4),只有移动区的数据被再次访问到才会被放到头节点。固定区的缓存页被再次访问到的时候,不会进行节点的移动。

2. 定时把LRU尾部缓存页刷入磁盘

定时任务线程,定时的进行操作

3. 空闲时间把flush链表中的数据刷入磁盘

mysql在空闲时间或者压力较小的时候,会把flush链表中的数据刷入到磁盘

设置多个buffer pool并发操作

多线程并发访问一个Buffer Pool,需要进行加锁,让一个线程先完成一系列的操作

[server]
innodb_buffer_pool_size = 8589934592
innodb_buffer_pool_instances = 4

buffer pool设置了8GB的总内存,然后设置了他应该有4个Buffer Pool,此时就是说,每个buffer pool的大小就是2GB

 chunk

innodb_buffer_pool_chunk_size参数控制chunk大小,默认值是128MB

一个mysql缓冲区 = N*bufferPool = N*bufferPool*M*chunk

每个bufferPool公用一套 free,flush,LRU链表

如果运行期增加bufferPool的大小,可以新建一系列的chunk,然后将chunk分配到不同的bufferPool上。

查看系统配置

SHOW ENGINE INNODB STATUS

Total memory allocated xxxx;
Dictionary memory allocated xxx
Buffer pool size xxxx
Free buffers xxx
Database pages xxx
Old database pages xxxx
Modified db pages xx
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young xxxx, not young xxx
xx youngs/s, xx non-youngs/s
Pages read xxxx, created xxx, written xxx
xx reads/s, xx creates/s, 1xx writes/s
Buffer pool hit rate xxx / 1000, young-making rate xxx / 1000 not xx / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: xxxx, unzip_LRU len: xxx
I/O sum[xxx]:cur[xx], unzip sum[16xx:cur[0]

(1)Total memory allocated,这就是说buffer pool最终的总大小是多少
(2)Buffer pool size,这就是说buffer pool一共能容纳多少个缓存页
(3)Free buffers,这就是说free链表中一共有多少个空闲的缓存页是可用的
(4)Database pages和Old database pages,就是说lru链表中一共有多少个缓存页,以及冷数据区域里的缓存页数量
(5)Modified db pages,这就是flush链表中的缓存页数量
(6)Pending reads和Pending writes,等待从磁盘上加载进缓存页的数量,还有就是即将从lru链表中刷入磁盘的数量、即将从flush链表中刷入磁盘的数量
(7)Pages made young和not young,这就是说已经lru冷数据区域里访问之后转移到热数据区域的缓存页的数量,以及在lru冷数据区域里1s内被访问了没进入热数据区域的缓存页的数量
(8)youngs/s和not youngs/s,这就是说每秒从冷数据区域进入热数据区域的缓存页的数量,以及每秒在冷数据区域里被访问了但是不能进入热数据区域的缓存页的数量
(9)Pages read xxxx, created xxx, written xxx,xx reads/s, xx creates/s, 1xx writes/s,这里就是说已经读取、创建和写入了多少个缓存页,以及每秒钟读取、创建和写入的缓存页数量
(10)Buffer pool hit rate xxx / 1000,这就是说每1000次访问,有多少次是直接命中了buffer pool里的缓存的
(11)young-making rate xxx / 1000 not xx / 1000,每1000次访问,有多少次访问让缓存页从冷数据区域移动到了热数据区域,以及没移动的缓存页数量
(12)LRU len:这就是lru链表里的缓存页的数量
(13)I/O sum:最近50s读取磁盘页的总数
(14)I/O cur:现在正在读取磁盘页的数量
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值