掰扯下Innodb内存架构之BufferPool

  1. 我们都知道mysql中的数据最终都会存到磁盘上,而我们又知道磁盘的读写速度和cpu不是在一个数量级上,所以我们猜测mysql存储引擎里必然有缓冲这一概念,本节我们就好好掰扯掰扯myslq中的缓存.
  2. 先到官网看看,存储innodb存储引擎的结构
    掰扯下Innodb内存架构之BufferPool_第1张图片
    从上图我们可以看到,INNODB架构,大致分为内存部分结构和磁盘部分结构,
    而内存部分又有BufferPool,ChangeBuffer,Adaptive Hash Index,LogBuffer等
    .我们将按照本图内存部分结构一点一点掰扯每一个缓存部分.
    3:首先来看BufferPool
  • 说白了就是内存里一个最主要的缓存数据,并且在专用服务器上(这里可以理解mysql的生产环境) 80%的物理内存都分配给了buffer pool。 可见buffer的重要性。
  • 那数据在buffer里是怎么存储的呢? 在看官方给的架构图
    掰扯下Innodb内存架构之BufferPool_第2张图片
    可从上图看出,新读入的数据都放在old列表,并且不会替换掉new列表中的热点数据. 那问题来了,什么时候old列表中数据会进入new列表呢?
    其实是进入buffer pool的数据,能被真正读取到, 并停留一定时间窗口,才会进入new列表 [有点像jvm内存分代,多大年龄可以进入老年代].

    其实真实的情况是: 首先mysql会预读数据 [局部性原理,大家可以自行了解] 另外加上上面说的全表扫描 mysqldump等. 这两种情况, 使进入的buffer pool中的数据并不一定被读到, 所以不能直接把热点数据给置换掉,才弄出来new列表和old列表,并且old列表的数据被访问到,且经历过T时间[时间窗口] 才会进入new列表.

    3:实战看下buffer pool相关的部分

  • 先本能到看下数据库关于buffer pool提供了哪些参数

窗口执行 show variables like '%buffer_pool%';
掰扯下Innodb内存架构之BufferPool_第3张图片
好像看不太懂,还是从buffer pool的数据结构反推应该有哪些配置吧.

  • 首先我们应该想到的是 一个mysql实例允许有几个buffer pool. 看上面架构图,好像只有一个,通过翻查资料,从INNODB1.0.X之后,允许有多个缓冲池实例. 所以找下肯定有缓冲池实例的配置.
    没错 innodb_buffer_pool_instances=1 默认一个.
    另外 突然扒到information_schema 里有INNODB_BUFFER_POOL_STATS表. 猜测从里能查看缓冲池状态信息. 先看看在说.
    掰扯下Innodb内存架构之BufferPool_第4张图片

可以看到有好多字段, 但有个POOL_ID=0 可见我本地就一个缓冲池.

  • 其次就是缓冲池大小
    没错 innodb_buffer_pool_size=134217728
  • 有了大小了,我们知道缓冲池分别new列表和old列表 所以肯定有控制分割比例的配置
    没错 innodb_old_blocks_pct=37 官网给的是3/8处. 可见这个是个经验值,或者有什么破定律使这个值最合适. 不废话,去官网看看咋解释的.

掰扯下Innodb内存架构之BufferPool_第5张图片
innodb_old_blocks_pct代表old列表的大小,范围[5,95] 其他自己到官网看吧.

  • 不过从上图又发现时间窗口的配置了

innodb_old_blocks_time=1000 默认1s

综合innodb_old_blocks_pct和innodb_old_blocks_time 有两种情况
如果业务中经常出现表扫描, 这时候就该把innodb_old_blocks_pct调小, 把innodb_old_blocks_time调大,避免很多预读的数据进入缓冲区.
如果业务中没有大量的表扫描. 这时候就该把innodb_old_blocks_pct调大,把innodb_old_blocks_time减小,让热点数据尽快进入new列表.减少磁盘io,提高性能.

  • 现在我们宏观看下整个buffer pool, 我们能不能对他了解的更多.
    有多少个buffer pool 我们已经知道. 大小我们也知道. new列表和old列表大小我们也知道. 现在唯一不知道的是buffer pool里缓存了多少页数据? 从old列表跑到new列表的量,频率等?
    还有个疑问点,上面POOL_SIZE=8191 和 innodb_buffer_pool_size=134217728 不是一个概念? 那POOL_SIZE=8191是什么概念呢?
    终于又从information_schema中发现两张表:
    掰扯下Innodb内存架构之BufferPool_第6张图片

INNODB_BUFFER_PAGE
INNODB_BUFFER_PAGE_LRU
先看第一张表:INNODB_BUFFER_PAGE
掰扯下Innodb内存架构之BufferPool_第7张图片
其实是LRU列表中的页信息. 从这里我们可以得出,BUFFER POOL 中不仅仅只有一个LRU列表,还有其他缓存信息.

  • 那LRU列表中 old到new这些频率怎么看? 命中率怎么看? 其实上面有个图已经有这些信息了,在来看看.
    掰扯下Innodb内存架构之BufferPool_第8张图片

HIT_RATE:表示命中率 不用说,越高越好.
PAGES_MADE_YONG: 这个是从old列表到new列表的数量。

另外我们发现: FREE_BUFFERS: 7704

        DATABASE_PAGES: 487
        POOL_SIZE: 8191
        

7704+487=8191;
可见buffer_pool 为2部分组成lru[487]+free_buffers[7704]
除来buffer_pool innodb内存还有其他部分
这里推荐大家没事多喵喵官网:
14.5.1 Buffer Pool

14.5.2 Change Buffer

14.5.3 Adaptive Hash Index

14.5.4 Log Buffer
其他的缓存我们下一次在一一分析.

你可能感兴趣的:(mysql优化,innodb,java,架构,mysql索引)