美文网首页JavaIT技术篇
认识Mysql中的缓存InnoDB Buffer Poll

认识Mysql中的缓存InnoDB Buffer Poll

作者: 挪威的senlin | 来源:发表于2020-04-20 00:10 被阅读0次

     如何提高系统的读的效率?使用缓存。如何提高系统写的效率?使用缓存。提高读写效率的关键在于减小磁盘I/O,特别是随机磁盘I/O。平时我们使用缓存主要用在提高查询效率上面,很少在提高写入效率上考虑缓存。本文将介绍Mysql在读写中如何运用缓存才提高自身的读写效率。

    Buffer Poll

    定义

     buffer poll是InnoDB维护的一个内存区域,用于存放表和索引数据。buffer poll的存在加快了mysql的读写速度。buffer poll是按页存储数据,并用链表的数据结构对buffer poll进行管理。

    淘汰算法

     buffer poll既然是内存中的区域,数据大小是有限的。就需要对内存区域的进行管理,使用的是LRU(Least recently used)算法,只不过Mysql对于传统的LRU算法做了一些改进,提高自己的缓存命中率。
    - LUR
    经典的LUR算法,使用一个链表链表实现,在进行数据读写操作的时候如下步骤:

    1. 数据存在链表中,将其移动到头节点;
    2. 数据不存在链表中,将数据放入头结点,并且这是判断是否超过了链表的长度,如果超过了限制长度,将尾节点淘汰。


      LUR

     这种LUR算法看似没有什么问题。但是在Mysql中如果出现查询了一个很冷门数据量的又很大的表这种业务场景时,就会出现问题。假设我现在buffer poll只有50M,但是我查询了一个数据量有100M的表,这个表平时又很少使用,如果使用LUR算法就会把以前缓存的热点数据全部淘汰掉,而新放入buffer poll中的数据很长一段时间都不会再访问,这样新的操作又要进行大量的磁盘I/O才能将热点数据重新缓存回来。所以mysql针对这种情况对LUR算法做了一些改变。
    - 变种LUR

    图片来自官网
     mysql将buffer poll 列表按照5:3的比例分为新旧两个部分,这样设计之后,该算法的读写操作步骤如下:
    • 数据在new sublist区域,将数据移动到yong区域的头结点;
    • 数据不存在buffer pool中,将其插入中点(old sublist的头结点),淘汰掉old sublist的尾节点;
    • 数据在old sublist中,若这个数据页在 LRU 链表中存在的时间超过了 1 秒,就把它移动到new sublist的头结点,如果这个数据页在 LRU 链表中存在的时间短于 1 秒,位置保持不变。1 秒这个时间,是由参数 innodb_old_blocks_time 控制的。其默认值是 1000,单位毫秒。

     采用这种算法,那种不带where条件的select操作,不会导致buffer poll中的缓存的数据受到很大的影响。因为这种查询都是顺序读,只会存在于old sublist,在old sublist中就会淘汰掉,而不会影响到new sublist中的数据。

    更新优化

     上面是buffer pool对查询的优化,这里将介绍buffer pool对数据更新的优化。首先,先要知道mysql在进行一个更新操作的步骤是什么。


    更新操作

     由上面的图可知,mysql执行一个更新操作,并不是直接去更改磁盘上的数据,而是去更改缓存并标记该页为脏页,然后写入日志作为持久化。这样的一个更新流程首先更改缓存中的数据比更改磁盘上的数据要快上很多,然后写入日志这一步是顺序写,没有随机I/O,操作也很快。然后mysql等待一个合适的时机将脏页的数据刷入磁盘。
     这种缓存策略被称为Write Back(写回)策略,操作系统的page cache也是采用的这种策略,提高了写的效率。

    Change Buffer

     change buffer是针对非聚簇索引(secondary index)的数据更改(insert、update、delete)的优化而存在的特殊的数据结构。在对非聚簇索引进行更改操作的时候,如果数据不在内存中,先将更改操作先记录到change buffer中,在之后的查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。
    以下为官网介绍:

    The change buffer is a special data structure that caches changes to secondary index pages when those pages are not in the buffer pool. 
    The buffered changes, which may result from INSERT, UPDATE, or DELETE operations (DML), 
    are merged later when the pages are loaded into the buffer pool by other read operations.
    
    图片来自官网

     为什么是非聚簇索引才能使用change buffer。因为不像聚簇索引,非聚簇索引通常非唯一,更改一个非聚簇索引顺序相对比较随机,将更改操作先写入chang buffer,随后做一个合并操作,这样可以避免查找非聚餐索引到内存所产生的大量随机I/O。如果是唯一索引不能使用change buffer,因为需要将数据加载到内存中判断索引是否已经存在,所以唯一索引和非唯一索引在更改数据会多一步将数据加载到内存的动作。

    总结

     本文了解了mysql缓存的作用,怎么提高读的效率和怎么提高写的效率。这些都是需要学习的知识点,以后如果遇到类似的场景将经典的解决方案运用到自己的项目之中。

    参考:
    https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html
    https://dev.mysql.com/doc/refman/8.0/en/innodb-change-buffer.html
    普通索引和唯一索引,应该怎么选择?
    日志系统:一条SQL更新语句是如何执行的?

    相关文章

      网友评论

        本文标题:认识Mysql中的缓存InnoDB Buffer Poll

        本文链接:https://www.haomeiwen.com/subject/pfnibhtx.html