change buffer(把改变的操作缓存起来)(提升语句执行效率)
- 当需要更新数据页的时候,如果数据页在内存中就直接更新。不在内存中的话,在不影响数据一致性的前提下(行锁竞争引发数据不一致)。innodb会将这些更新操作缓存在change buffer中。(减少磁盘随机读操作)
- 在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作(merge)
- 系统也有后台线程会定期merge,在数据库正常关闭(shutdown)的过程中,也会执行merge操作。
- change buffer也可以进行持久化、写入到硬盘上;
- change buffer只可以用在普通索引,不可以用在唯一索引上。因为当更新、插入数据的时候,唯一索引需要判断该更改是否在表中满足唯一性约束。也就是必须通过将数据页读取到内存中判断是否已经存在这么一条记录。(建议:当业务逻辑已经保证不会插入、更新相同的记录,那么尽量使用普通索引,性能会更好)
- change buffer用的是buffer pool里的内存,可以通过参数innodb_change_buffer_max_size来动态设置,这个参数设置为50的时候,表示change buffer最多只能占用buffer pool的50%;
- change buffer适合写多读少的业务场景,因为即使更新语句使用了change buffer机制,减少了更新时的随机读磁盘操作,但是如果该业务查询场景很多,亦或者需要更新完又立刻查询的话。那么又会立刻触发merge操作,这样随机访问IO的次数不仅不会减少,反而增加了change buffer的维护代价。
- change buffer对inser、delete操作也同样适用。insert操作中,由于主键索引肯定是唯一的,所以主键索引的插入肯定是不适用的,只适用于插入操作时的二级索引的维护(不需要立刻对二级索引进行数据写入,缓存起来,再后台刷盘);
change buffer 和redo log的联系
- change buffer使得一个更新操作可以不用把数据页立刻读取到内存中(减少了随机读的操作)
- redo log使得一个更新操作可以不用立刻把数据写入到磁盘中(减少了随机写入的操作)
- change buffer新写入的信息也会被记录到redo log中,使得mysql断电的时候也可以从redo log中恢复change buffer(redo log未commit的话,就要看binlog有无commit了,有commit的话就可以通过binlog恢复redo log再恢复change buffer,未commit的话这部分数据就会丢失了)