概述
今天谈谈mysql的innodb缓存和介绍一下怎么统计其命中率。

1、InnoDB的Buffer Pool
Buffer Pool本质上是InnoDB向操作系统申请的一段连续的内存空间,可以通过innodb_buffer_pool_size来调整它的大小。
那么怎么将磁盘上的页缓存到内存中的Buffer Pool中呢?是直接把需要缓存的页向Buffer Pool里一个一个往里怼么?其实为了更好的管理这些被缓存的页,InnoDB为每一个缓存页都创建了一些所谓的控制信息,这些控制信息包括该页所属的表空间编号、页号、页在Buffer Pool中的地址,一些锁信息以及LSN信息,当然还有一些别的控制信息,这里就忽略了,反正大家也记不住。
每个缓存页对应的控制信息占用的内存大小是相同的,我们就把每个页对应的控制信息占用的一块内存称为一个控制块吧,控制块和缓存页是一一对应的,它们都被存放到 Buffer Pool 中,其中控制块被存放到 Buffer Pool 的前边,缓存页被存放到 Buffer Pool 后边,所以整个Buffer Pool对应的内存空间看起来就是这样的:

每一个控制块都对应一个缓存页,那在分配足够多的控制块和缓存页后,最后剩余的那点儿空间不够一对控制块和缓存页的大小时这部分内存空间就被称为碎片了。
2、缓存页的哈希处理
当我们需要访问某个页中的数据时,就会把该页加载到Buffer Pool中,如果该页已经在Buffer Pool中的话直接使用就可以了。那么问题也就来了,我们怎么知道该页在不在Buffer Pool中呢?难不成需要依次遍历Buffer Pool中各个缓存页么
其实MySQL是根据表空间号 + 页号来定位一个页的,也就相当于表空间号 + 页号是一个key,缓存页就是对应的value,怎么通过一个key来快速找着一个value呢?这里就是用哈希表来实现了。
所以可以用表空间号 + 页号作为key,缓存页作为value创建一个哈希表,在需要访问某个页的数据时,先从哈希表中根据表空间号 + 页号看看有没有对应的缓存页,如果有,直接使用该缓存页就好,如果没有,那就从Free链表中选一个空闲的缓存页,然后把磁盘中对应的页加载到该缓存页的位置
3、InnoDB中查看Buffer Pool的状态信息
作为MySQL的管理人员,我们有时候需要查看一下Buffer Pool中的情况,这时候就可以用命令:
show engine innodb status G来看了。

- Buffer pool size 代表该Buffer Pool可以容纳多少缓存页,注意,单位是页!
- Free buffers代表当前Buffer Pool还有多少空闲缓存页,也就是Free链表中还有多少个节点。
- Database pages代表LRU链表中的页的数量,包含young和old两个区域的节点数量。
- Old database pages代表LRU链表old区域的节点数量。
- Modified db pages代表脏页数量,也就是FLU链表中节点的数量。
- Pages made young代表从old区域移动到young区域的节点数量,not young代表old区域没有移动到young区域就被淘汰的节点数量。后边跟着移动的速率。
- Pages read、created、written代表innodb读取,创建,写入了多少页。后面跟着读取、创建、写入的速率。
- LRU len代表LRU链表中节点的数量。
- unzip_LRU代表非16K大小的页的数量,这些非16K大小的页都是被unzip_LRU链表管理的
4、Buffer Pool缓存命中率统计
4.1、show 方式去查看:
show status like '%innodb_buffer_pool_pages%';
计算方式:(total-free)/total * 100%

4.2、sql方式:
select VARIABLE_NAME,VARIABLE_VALUE from information_schema.global_status where VARIABLE_NAMEin ('Innodb_buffer_pool_pages_total','Innodb_buffer_pool_pages_free');

4.3、查看innodb状态来统计
show engine innodb status G
计算方式:(total-free)/total * 100%

觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~
