什么是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的位置。
从图中右侧信息可以做一些小总结:
工作流程
为了能让大家更清楚的了解整个流程,我们用结合图的方式进行举例,举例的前提是适合Change Buffer使用场景,使用场景文章结尾有总结。
图中我们把主要的流程用图画出来就可以,更详细的关于一条Update的更新可以看往期分享:
写入流程
执行两条Insert语句,其中左侧的要更新的数据页 Page1 不在Buffer Pool,而右侧需要更新的数据页Page2在Buffer Pool缓存中。
这里会写两次内存:一次是修改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。
为什么Change Buffer只能是缓存非唯一索引?
Change Buffer只适用于非唯一索引数据的变更修改情况,而不能为唯一索引或者主键数据的原因在于【唯一索引需要做唯一性校验】
那么是怎么做唯一性校验的呢?对唯一索引进行更新时必须将对应的数据页加载到Buffer Pool缓存中进行校验,自然就不会用到Change Buffer啦
什么时候会把Change Buffer 数据持(merge)到磁盘上呢?
我们知道Change Buffer只是缓存了数据的变更操作,但是没有实际落盘持久化,以下情况会触发Merge落盘。
但是基本不会出现Redo Log写满的情况,这个种情况出现的话,数据库都不可用了
Change Buffer适合什么样的业务场景呢?
主要适合这两种情景: 数据大部分是非唯一索引 写多读少,并且修改后不需要立即返回修改值
相反在这两种场景反而不适合,Change Buffer 反而会成了负担,增加了复杂度。就是上面合适场景的反向, 数据库是唯一索引,修改后需要立即读取修改值。
👨👩 你好,朋友,希望本文对你有帮助~🌐
欢迎点赞 👍、收藏 💙、关注 💡 三连支持一下~🎈
我会继续输出更高质量文章进行分享~🙇💻