MySQL写缓冲Change Buffer原理解读

2023年 7月 22日 60.0k 0

什么是Change Buffer

我们知道MySQL在查询的时候有一种预读机制, 为了提高同样数据的查询效率,会将磁盘中的数据加载到内存中,Buffer Pool(缓冲池)就承担了这么一个角色。

如果每次写操作,数据库都直接更新磁盘中的数据,会很占磁盘IO,那么MySQL是怎么优化的呢?

当用户执行SQL对非唯一索引进行更改时,如果索引对应的数据页不在缓存中时,InnoDB不会直接加载磁盘数据到缓存数据页中,而是缓存对这些更改操作(buffer changes)。

缓存区的更改操作会在磁盘数据被其它读操作加载到缓存中时合并(Merge)到对应的缓存数据页中。

InnoDB在Buffer Pool中开辟了一块内存,用来存储变更记录,用来缓存写操作到内存,就是Change Buffer。

MySQL使用它的目的是降低写操作的磁盘IO,提升数据库性能。

OK,Change Buffer基本概念了解了,继续往下读!

Change Buffer结构

我把InnoDB和Change Buffer的结构整合了一下,让我们更清楚 Change Buffer的位置。

从图中右侧信息可以做一些小总结:

  • ChangeBuffer用于存储SQL变更操作;
  • ChangeBuffer中的每个变更操作都有其对应的数据页,并且该数据页未加载到缓存中;
  • 当ChangeBuffer中变更操作对应的数据页加载到缓存中后,InnoDB会把变更操作Merge到数据页上;
  • InnoDB会定期加载Change Buffer中操作对应的数据页到缓存中,并Merge变更操作
  • 工作流程

    为了能让大家更清楚的了解整个流程,我们用结合图的方式进行举例,举例的前提是适合Change Buffer使用场景,使用场景文章结尾有总结。

    图中我们把主要的流程用图画出来就可以,更详细的关于一条Update的更新可以看往期分享:

    写入流程

    执行两条Insert语句,其中左侧的要更新的数据页 Page1 不在Buffer Pool,而右侧需要更新的数据页Page2在Buffer Pool缓存中。

  • 数据页Page1不在Buffer Pool中的话将写入Change Buffer,缓存下对Page1的修改
  • 数据页Page2在缓存中,直接更新(最终写入磁盘)
  • 这里会写两次内存:一次是修改Buffer Pool的数据页、另一次是Change buffer中记录这个写入操作

    但是会写一次磁盘:不对啊,应该会写入两次Redo Log啊,并不是的,因为两次操作合在一起写了一次磁盘,还是顺序写

    注意:默认下ibdata存放InnoDB表(InnoDB数据字典)元数据、undo logs、change buffer, doublewrite buffer

    写入后再读

    读Page2的时候很好理解,直接从Buffer Pool 中返回,

    但是读Page1时,需把Page1从磁盘读入内存,然后将Change Buffer里面的操作日志,Merge生成一个正确版本并返回结果。

    再看总结

    SQL的变更操作什么时候被放在Change Buffer?

    从文章开始我们就知道并不是所有的MySQL操作都会进入Change Buffer ,其实只有符合以下几个条件的,才会在执行阶段不直接修改数据页,而是放入Change Buffer。

  • SQL是对非唯一键数据的修改
  • 修改的数据页不在 Buffer Pool缓冲中
  • 修改后不需要立即返回变更后的数据
  • 该SQL是DML、不是DDL (也就是修改类型是对数据的修改)
  • 为什么Change Buffer只能是缓存非唯一索引?

    Change Buffer只适用于非唯一索引数据的变更修改情况,而不能为唯一索引或者主键数据的原因在于【唯一索引需要做唯一性校验】

    那么是怎么做唯一性校验的呢?对唯一索引进行更新时必须将对应的数据页加载到Buffer Pool缓存中进行校验,自然就不会用到Change Buffer啦

    什么时候会把Change Buffer 数据持(merge)到磁盘上呢?

    我们知道Change Buffer只是缓存了数据的变更操作,但是没有实际落盘持久化,以下情况会触发Merge落盘。

  • 访问变更操作对应的数据页
  • InnoDB后台线程定期Merge
  • Buffer Pool缓冲空间不足
  • 数据库正常关闭时
  • Redo Log 写满时
  • 但是基本不会出现Redo Log写满的情况,这个种情况出现的话,数据库都不可用了

    Change Buffer适合什么样的业务场景呢?

    主要适合这两种情景: 数据大部分是非唯一索引 写多读少,并且修改后不需要立即返回修改值

    相反在这两种场景反而不适合,Change Buffer 反而会成了负担,增加了复杂度。就是上面合适场景的反向, 数据库是唯一索引,修改后需要立即读取修改值。

    👨👩 你好,朋友,希望本文对你有帮助~🌐
    欢迎点赞 👍、收藏 💙、关注 💡 三连支持一下~🎈
    我会继续输出更高质量文章进行分享~🙇💻

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论