写缓冲(change buffer),此次完全懂了!!!

上篇《缓冲池(buffer pool),完全懂了!》介绍了InnoDB缓冲池的工做原理。算法

简单回顾一下:
写缓冲(change buffer),此次完全懂了!!!
(1)MySQL数据存储包含内存与磁盘两个部分;
(2)内存缓冲池(buffer pool)以页为单位,缓存最热的数据页(data page)与索引页(index page);
(3)InnoDB以变种LRU算法管理缓冲池,并可以解决“预读失效”与“缓冲池污染”的问题;
画外音:细节详见《缓冲池(buffer pool),完全懂了!》。shell

毫无疑问,对于读请求,缓冲池可以减小磁盘IO,提高性能。问题来了,那写请求呢?数据库

状况一

假如要修改页号为4的索引页,而这个页正好在缓冲池内。
写缓冲(change buffer),此次完全懂了!!!
如上图序号1-2:
(1)直接修改缓冲池中的页,一次内存操做;
(2)写入redo log,一次磁盘顺序写操做;
这样的效率是最高的。
画外音:像写日志这种顺序写,每秒几万次没问题。缓存

是否会出现一致性问题呢?

并不会。
(1)读取,会命中缓冲池的页;
(2)缓冲池LRU数据淘汰,会将“脏页”刷回磁盘;
(3)数据库异常奔溃,可以从redo log中恢复数据;架构

何时缓冲池中的页,会刷到磁盘上呢?

按期刷磁盘,而不是每次刷磁盘,可以下降磁盘IO,提高MySQL的性能。
画外音:批量写,是常见的优化手段。ide

状况二

假如要修改页号为40的索引页,而这个页正好不在缓冲池内。
写缓冲(change buffer),此次完全懂了!!!
此时麻烦一点,如上图须要1-3:
(1)先把须要为40的索引页,从磁盘加载到缓冲池,一次磁盘随机读操做;
(2)修改缓冲池中的页,一次内存操做;
(3)写入redo log,一次磁盘顺序写操做;性能

没有命中缓冲池的时候,至少产生一次磁盘IO,对于写多读少的业务场景,是否还有优化的空间呢?优化

这便是InnoDB考虑的问题,又是本文将要讨论的写缓冲(change buffer)。
画外音:从名字容易看出,写缓冲是下降磁盘IO,提高数据库写性能的一种机制。线程

什么是InnoDB的写缓冲?

在MySQL5.5以前,叫插入缓冲(insert buffer),只针对insert作了优化;如今对delete和update也有效,叫作写缓冲(change buffer)。日志

它是一种应用在非惟一普通索引页(non-unique secondary index page)不在缓冲池中,对页进行了写操做,并不会马上将磁盘页加载到缓冲池,而仅仅记录缓冲变动(buffer changes),等将来数据被读取时,再将数据合并(merge)恢复到缓冲池中的技术。写缓冲的目的是下降写操做的磁盘IO,提高数据库性能。
画外音:R了狗了,这个句子,好长。

InnoDB加入写缓冲优化,上文“状况二”流程会有什么变化?

假如要修改页号为40的索引页,而这个页正好不在缓冲池内。
写缓冲(change buffer),此次完全懂了!!!
加入写缓冲优化后,流程优化为:
(1)在写缓冲中记录这个操做,一次内存操做;
(2)写入redo log,一次磁盘顺序写操做;
其性能与,这个索引页在缓冲池中,相近。
画外音:能够看到,40这一页,并无加载到缓冲池中。

是否会出现一致性问题呢?

也不会。
(1)数据库异常奔溃,可以从redo log中恢复数据;
(2)写缓冲不仅是一个内存结构,它也会被按期刷盘到写缓冲系统表空间;
(3)数据读取时,有另外的流程,将数据合并到缓冲池;

不妨设,稍后的一个时间,有请求查询索引页40的数据。
写缓冲(change buffer),此次完全懂了!!!
此时的流程如序号1-3:
(1)载入索引页,缓冲池未命中,此次磁盘IO不可避免;
(2)从写缓冲读取相关信息;
(3)恢复索引页,放到缓冲池LRU里;
画外音:能够看到,40这一页,在真正被读取时,才会被加载到缓冲池中。

还有一个遗漏问题,为何写缓冲优化,仅适用于非惟一普通索引页呢?
InnoDB里,汇集索引(clustered index)和普通索引(secondary index)的异同,《1分钟了解MyISAM与InnoDB的索引差别》有详尽的叙述,再也不展开。

若是索引设置了惟一(unique)属性,在进行修改操做时,InnoDB必须进行惟一性检查。也就是说,索引页即便不在缓冲池,磁盘上的页读取没法避免(不然怎么校验是否惟一?),此时就应该直接把相应的页放入缓冲池再进行修改,而不该该再整写缓冲这个幺蛾子。

除了数据页被访问,还有哪些场景会触发刷写缓冲中的数据呢?
还有这么几种状况,会刷写缓冲中的数据:
(1)有一个后台线程,会认为数据库空闲时;
(2)数据库缓冲池不够用时;
(3)数据库正常关闭时;
(4)redo log写满时;
画外音:几乎不会出现redo log写满,此时整个数据库处于没法写入的不可用状态。

什么业务场景,适合开启InnoDB的写缓冲机制?

先说何时不适合,如上文分析,当:
(1)数据库都是惟一索引;
(2)或者,写入一个数据后,会马上读取它;
这两类场景,在写操做进行时(进行后),原本就要进行进行页读取,原本相应页面就要入缓冲池,此时写缓存反倒成了负担,增长了复杂度。

何时适合使用写缓冲,若是:
(1)数据库大部分是非惟一索引;
(2)业务是写多读少,或者不是写后马上读取;
可使用写缓冲,将本来每次写入都须要进行磁盘IO的SQL,优化按期批量写磁盘。
画外音:例如,帐单流水业务。

上述原理,对应InnoDB里哪些参数?

有两个比较重要的参数。
写缓冲(change buffer),此次完全懂了!!!
参数:innodb_change_buffer_max_size
介绍:配置写缓冲的大小,占整个缓冲池的比例,默认值是25%,最大值是50%。
画外音:写多读少的业务,才须要调大这个值,读多写少的业务,25%其实也多了。

参数:innodb_change_buffering
介绍:配置哪些写操做启用写缓冲,能够设置成all/none/inserts/deletes等。

但愿你们有收获,思路比结论重要。
写缓冲(change buffer),此次完全懂了!!!架构师之路-分享技术思路相关推荐:《6条shell小技巧,让脚本更专业 | 1分钟系列》《MyISAM与InnoDB的索引差别 | 1分钟系列》《缓冲池(buffer pool),此次完全懂了!!!》《学会聆听,职场最重要的事情!!!》

相关文章
相关标签/搜索