change buffer
当更新一个数据页时候,如果页在内存,就直接更新,如果没,在不影响数据一致性的情况下,innodb会将这些更新数据操作缓存在change buffer中,这样就不需要在磁盘读取数据页了,下次查询需要访问整个数据页时候,,将数据页读取内存,执行change buffer中与整个数据页有关的操作
change buffer在内存中copy,也会被写入磁盘
当访问数据页时候,change buffer有数据操作merge保存,后台也有线程定期执行merge,当数据库正常shutdown也会执行merge
如果能够将跟新数据先记录在change buffer,减少读磁盘,语句执行速度快,而且读数据需要占用buffer pool,所以这种方式可以避免占用内存,提升内存使用率
什么时候使用
插入(4,400)
情况
数据页在内存中
唯一索引:找到3,5之间的位置,判断到没有冲突,插入这个值,语句执行结束
普通索引
找到3,5之间的位置,插入这个值,语句结束
数据页不在内存中
唯一索引
读取数据页,判断没有冲突,插入数据,语句执行结束
普通索引
将记录在change buffer,语句执行结束
将数据载入内存和随机读非常耗性能,changge buffer可以减少磁盘访问量
dba反馈某个业务内存命中率突然冲99%降低到了75%,整个系统处于阻塞状态,更新语句全部堵住。原因是业务有大量insert操作,dba在前一天将其中的某个普通索引改成了唯一索引
使用场景
change buffer 只限于普通索引的情况下,change buffer记录越多,收益就越大,对应读多写少的业务非常适用,但是如果更新完数据,马上读取这个数据,这是会触发merge ,这样就增加了change buffer的维护代价
如果是历史数据,可以将唯一索引改为普通索引,然后将change buffer尽量开大,这个确保历史数据的插入速度
redo log
insert into t(id,k) values(id1,k1),(id2,k2)
k1 在内存直接更新内存,
k2不在内存直接更新change buffer
写入redo log 整个过程只更新了两次内存,写了一次磁盘log,还是顺序写入
读取插入条件数据,k1如果在内存直接返回,k2不在内存读取page页,然后merge change buffer生成一个正确的版本返回结果
对比
redo log主要节省的是随写磁盘IO消耗(转成顺序写),change buffer 主要节省的是随机读磁盘IO消耗