Change Buffer是Mysql优化二级索引写操作的策略,Change Buffer主要针对非唯一键索引的,通过缓存二级索引的更新操作,目的是减少磁盘IO来提高性能。当数据页读取数据时,Change Buffer会将变更的数据据合并到缓存页中。
Change Buffer可以通过参数做一些配置,我们在Mysql中查询其基本的配置信息:
show variables like 'innodb_change_buffer%';

innodb_change_buffer_max_size:
配置写缓冲区占整个Buffer Pool大小的比例,默认值是25,它表示change bufer最大可以占用innodb Buffer Pool的25%,最大可设置的值为50%。写多读少的业务可以适当调大这个值,读多写少的业务,25%也是够用的。
innodb_change_buffering:
默认值是all,表示所有的非唯一普通索引页写入都使用Change Buffer,当然也可以设置其他的值,下表整理一些可以设置的值:
Change Buffer的参数innodb_change_buffering可以根据自己的项目的实际需要做出适当的调整,下面展示了Change Buffer与Buffer Pool之间的关系图:

假设现在要更新的数据在page=7中数据并且page=7的数据不在Buffer Pool中,此时得更新操作如下所示:

当要更新page=7上得数据时,Mysql先通过缓存的hash来判断当前得数据是否加载到Buffer Pool上,如果此时发现数据没有加载到Buffer Pool中得时候,Mysql也不会去磁盘加载数据而是直接记录对page=7得数据修改记录放在Change Buffer上,并且还将数据记录到Log Buffer上。数据的更新记录在Change Buffer上后采用异步线程同步数据到磁盘上。
假设此时来了一个查询page=7上的数据的线程,其查询数据的过程如下图所示:

首先Mysql通过缓存页hash表判断数据是否在Buffer Pool上的缓存页中,如果没有数据就从磁盘加载数据到缓存页中,磁盘数据加载到Buffer Pool的缓存页是没有修改之前的数据,Change Buffer会通过merge操作将修改后的数据同步到缓存页中,经过merge操作后使得Buffer Pool缓存页中的数据是最新的数据,然后返回给客户端。通过Change Buffer可以减少一次IO操作进而提升了Mysql的效率。
总结:
(1) Change Buffer是Mysql中优化二级索引写操作,为什么不能针对唯一索引呢?因为唯一索引需要检验数据库数据的唯一性,这样就需要加载磁盘数据到Buffer Pool中,此时就不需要使用Change Buffer了。
(2)Change Buffer主要适用于数据大部分是非唯一索引的写多读少并且修改后不需要立即返回修改值的场景,典型的应用有账单、日志系统等。
(3)如果要修改的数据已经在Buffer Pool中了,此时线程修改了缓存页上的数据后将缓存页对应的控制块信息加入flush链表上,然后通过flush链表同步脏页数据到磁盘上。




