当前位置: 首页 > 科技观察

写缓冲(changebuffer),这次我彻底明白了!!!

时间:2023-03-14 08:36:49 科技观察

篇《缓冲池(buffer pool),彻底懂了!》介绍了InnoDB缓冲池的工作原理。简要回顾:MySQL数据存储包括内存和磁盘两部分;内存缓冲池(bufferpool)以页为单位缓存最热的数据页(datapages)和索引页(indexpages);InnoDB使用LRU算法的一个变体来管理缓冲池,能够解决“预读失效”和“缓冲池污染”的问题;画外音:详见《缓冲池(buffer pool),彻底懂了!》。毫无疑问,对于读请求,缓冲池可以减少磁盘IO,提高性能。问题来了,写请求呢?情况一:如果要修改页号为4的索引页,而这个页恰好在缓冲池中。上图中数字1-2:直接修改缓冲池中的页面是内存操作;写入重做日志是顺序磁盘写操作;这个效率是最好的。画外音:像写日志一样顺序写是没有问题的,每秒几万次。会不会有一致性问题?并不真地。读取,缓冲池中的页面将被删除;缓冲池中的LRU数据将被淘汰,“脏页”将被刷新回磁盘;数据库会异常崩溃,可以从重做日志中恢复数据;什么时候缓冲池中的页面会被刷写到磁盘呢?定期刷新磁盘,而不是每次都刷新磁盘,可以减少磁盘IO并提高MySQL性能。画外音:批量写入是一种常见的优化方式。情况2如果要修改页号为40的索引页,而该页不在缓冲池中。这时候就有点麻烦了,如上图,需要1-3:首先,从磁盘加载需要40的索引页到缓冲池,一次随机磁盘读操作;修改缓冲池中的页面,一次内存操作;写入重做日志,磁盘顺序写操作;当没有活动缓冲池时,至少会产生一次磁盘IO。对于写多读少的业务场景还有优化空间吗?这是InnoDB考虑的问题,也是本文要讨论的问题讨论写缓冲(changebuffer)。画外音:从名字就很容易看出写缓冲是一种减少磁盘IO,提高数据库写性能的机制。InnoDB的写缓冲区是什么?MySQL5.5之前称为insertbuffer,只针对insert做了优化;现在对delete和update也有效,称为writebuffer(changebuffer)。是非唯一二级索引页不在缓冲池中时的一个应用,写入该页时,磁盘页不会立即加载到缓冲池中,而只是记录缓冲变化(bufferchanges),等待未来的数据被读取,然后将数据合并回缓冲池。写缓冲的目的是减少写操作的磁盘IO,提高数据库性能。画外音:R是狗,这句话好长。InnoDB加入写缓冲区优化,上面的“case2”过程会发生什么?假设要修改页号为40的索引页,而这个页恰好不在缓冲池中。加入writebuffer优化后,流程优化如下:将本次操作记录在writebuffer中,一次内存操作;写入重做日志,磁盘顺序写操作;它的性能类似于缓冲池中的这个索引页。画外音:如您所见,第40页没有加载到缓冲池中。会不会有一致性问题?没有。数据库异常crash,可以从redolog中恢复数据;writebuffer不仅仅是一个内存结构,它还会被周期性的刷新到writebuffer系统表空间;读取数据时,还有一个进程将数据合并到缓冲池中;可以假设稍后有请求查询索引页40的数据,此时的流程如序号1-3:加载索引页,未安装缓冲池,这个磁盘IO是不可避免的;从写缓冲区中读取相关信息;恢复索引页,放入缓冲池LRU;画外音:可以看出40页只有在真正读取时才会加载到缓冲池中。还有一个遗漏的问题,为什么writebuffer优化只适用于非唯一的普通索引页?在InnoDB中,聚簇索引(clusteredindex)与普通索引(secondaryindex)的异同由《1分钟了解MyISAM与InnoDB的索引差异》详细介绍,不再展开。如果索引设置了唯一性(unique)属性,InnoDB在执行修改操作时必须进行唯一性检查。也就是说,即使索引页不在缓冲池中,也无法避免磁盘上的页读取(否则如何检查是否唯一?),此时应该直接将相应的页放入bufferpool然后修改而不是整个writebuffer是个蛀虫。除了正在访问的数据页,还有哪些场景会触发缓冲区中的数据被刷新?还有几种情况会刷新缓冲区中的数据:有后台线程认为数据库空闲;数据库缓冲池不够用时;当数据库正常关闭时;当重做日志已满时;画外音:重做日志几乎从不满,整个数据库处于无法写入的不可用状态。哪些业务场景适合开启InnoDB的写缓冲机制?不合适的时候再说吧。上面分析过,当:数据库是唯一索引;或者,写入一条数据后,立即读取;这两类场景,在进行写操作时(操作后),应该读取页面,将对应的页面放入缓冲池中。这时候写缓存就成了负担,增加了复杂度。什么时候使用写缓冲是合适的,如果:大多数数据库是非唯一索引;生意是多写少读,或者写完不马上看;您可以使用写缓冲来替换每次写入都需要磁盘IO的SQL。优化定期批量写入磁盘。画外音:例如,计费交易。InnoDB中有哪些参数符合上述原则?有两个重要的参数。参数:innodb_change_buffer_max_size简介:配置写缓冲区的大小,占整个缓冲池的比例。默认值为25%,最大值为50%。画外音:对于写多读少的商家,需要加大这个值。对于读多写少的企业来说,25%其实太多了。参数:innodb_change_buffering简介:配置哪些写操作启用写缓冲,可以设置为all/none/inserts/deletes等,希望大家有所收获。想法比结论更重要。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文