暂无图片
暂无图片
19
暂无图片
暂无图片
暂无图片

MySQL各种“Buffer”之Change Buffer

GrowthDBA 2021-09-23
9208
上一篇文章MySQL各种“Buffer”之InnoDB Buffer Pool我们学习了InnoDB Buffer Pool的工作原理,其作用是减少MySQL读取数据时直接与磁盘打交道的次数。那么写入数据时MySQL是否做了减少IO的优化呢?答案是肯定的,Change Buffer闪亮登场。先放一张官档中Change Buffer的架构图:

(https://dev.mysql.com/doc/refman/5.7/en/innodb-change-buffer.html)

官档中对Change Buffer的概念是:更改缓冲区是一种特殊的数据结构,当二级索引页不在缓冲池中时,它会缓存对二级索引页的更改。可能由INSERT
UPDATE
DELETE(DML)
操作导致的缓冲更改,稍后在其他读取操作将页面加载到缓冲池时合并。

总觉着英文的官档翻译成中文很别扭,那今天就用通俗易懂的话来翻译和讲解一下Change Buffer的工作原理。

本文摘录自:

58沈剑-架构师之路-公众号文章《写缓冲(change buffer),这次彻底懂了!!!》

思考如何减少因数据写入导致的IO

MySQL基于写入数据如何减少IO的思考

  • 对于读请求缓冲池能够减少与磁盘打交道的次数,提升性能。但是,如果写数据请求也能减少和磁盘打交道的次数,那样性能不是更好吗?

这时也分为两种情况

  • 情况一:

假如要修改的页4正好在缓冲池内

处理过程为图中1、2:
1、直接修改缓冲池中的页,一次内存操作;
2、写入redo log,一次磁盘顺序写操作;
这样的效率是最高的(像写日志这种顺序写,每秒几万次没问题)。
  • 是否会出现一致性问题呢?
并不会
1、读取,会命中缓冲池的页;
2、缓冲池LRU数据淘汰,会将“脏页”刷回磁盘;
3、数据库异常奔溃,能够从redo log中恢复数据;
  • 什么时候缓冲池中的页,会刷到磁盘上呢?

定期刷磁盘,而不是每次刷磁盘,能够降低磁盘IO,提升MySQL的性能。(批量写,是常见的优化手段

  • 情况二:

假如要修改的这个页40正好不在缓冲池内

此时麻烦一点,处理过程为1、2、3

1、先把需要为40的索引页,从磁盘加载到缓冲池,一次磁盘随机读操作;

2、修改缓冲池中的页,一次内存操作;

3、写入redo log,一次磁盘顺序写操作;

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

 这即是InnoDB考虑的问题,写缓冲(change buffer)应用而生(从名字容易看出,写缓冲是降低磁盘IO,提升数据库写性能的一种机制)。

Change Buffer工作原理

Change Buffer概念

在MySQL5.5之前,叫插入缓冲(Insert Buffer),只针对INSERT做了优化;现在对DELETE和UPDATE也有效,叫做写缓冲(Change Buffer)

它是一种应用在非唯一普通索引页(non-unique secondary index page)不在缓冲池中,对页进行了写操作,并不会立刻将磁盘页加载到缓冲池,而仅仅记录缓冲变更(Buffer Changes),等未来数据被读取时,再将数据合并(Merge)恢复到缓冲池中的技术。写缓冲的目的是降低写操作的磁盘IO,提升数据库性能

Change Buffer工作原理

  • InnoDB加入写缓冲优化,上文“情况二”流程会有什么变化?
假如要修改页号为40的索引页,而这个页正好不在缓冲池内

加入写缓冲优化后,流程优化为

1、在写缓冲中记录这个操作,一次内存操作;

2、写入redo log,一次磁盘顺序写操作;

其性能与这个索引页在缓冲池中,相近(可以看到,40这一页,并没有加载到缓冲池中)。

  • 是否会出现一致性问题呢?
也不会
1、数据库异常奔溃,能够从redo log中恢复数据;
2、写缓冲不只是一个内存结构,它也会被定期刷盘到写缓冲系统表空间
3、数据读取时,有另外的流程,将数据合并到缓冲池;
  • 不妨设,稍后的一个时间,有请求查询索引页40的数据

此时的流程如序号1-3

1、载入索引页,缓冲池未命中,这次磁盘IO不可避免;

2、从写缓冲读取相关信息;

3、恢复索引页,放到缓冲池LRU里;(可以看到,40这一页,在真正被读取时,才会被加载到缓冲池中)

知识补充

Change Buffer只适用于非唯一普通索引页的原因

  • 为什么写缓冲优化,仅适用于非唯一普通索引页呢?
InnoDB里,聚集索引(Clustered Index))和普通索引(Secondary Index)存在异同。如果索引设置了唯一(Unique)属性,在进行修改操作时,InnoDB必须进行唯一性检查。也就是说,索引页即使不在缓冲池,磁盘上的页读取无法避免(否则怎么校验是否唯一!?),此时就应该直接把相应的页放入缓冲池再进行修改,而不应该再整写缓冲这个幺蛾子。

Change Buffer触发时机

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

Change Buffer适用场景

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

先说什么时候不适合,如上文分析,当

1、数据库都是唯一索引;

2、或者,写入一个数据后,会立刻读取它;

这两类场景,在写操作进行时(进行后),本来就要进行进行页读取,本来相应页面就要入缓冲池,此时写缓存反倒成了负担,增加了复杂度。

什么时候适合使用写缓冲,如果:

1、数据库大部分是非唯一索引;

2、业务是写多读少,或者不是写后立刻读取;

可以使用写缓冲,将原本每次写入都需要进行磁盘IO的SQL,优化定期批量写磁盘。例如,账单流水业务。

InnoDB里涉及Change Buffer的重要的参数

SHOW VARIABLES LIKE '%innodb_change_buffer_max_size%';SHOW VARIABLES LIKE '%innodb_change_buffering%';

  • 参数:innodb_change_buffer_max_size

介绍:配置写缓冲的大小,占整个缓冲池的比例,默认值是25%,最大值是50%。(写多读少的业务,才需要调大这个值,读多写少的业务,25%其实也多了)
  • 参数:innodb_change_buffering

介绍:配置哪些写操作启用写缓冲,可以设置成all/none/inserts/deletes等。(这个也好理解,就是见名知意,如果只配置成inserts,那就只对INSERT操作生效,以此类推)

小结

今天理论的知识不是很多,下面简单做一下总结:

1、Change Buffer是一种特殊的内存结构,它是一种应用在非唯一普通索引页(non-unique secondary index page)不在缓冲池中,对页进行了写操作并不会立刻将磁盘页加载到缓冲池而仅仅记录缓冲变更(Buffer Changes)等未来数据被读取时再将数据合并(Merge)恢复到缓冲池中的技术。写缓冲的目的是降低写操作的磁盘IO提升数据库性能

2、如果索引设置了唯一(Unique)属性,在进行修改操作时,InnoDB必须进行唯一性检查,是不能使用到Change Buffer的;

3、根据业务使用情况,可以指定Change Buffer占整个缓冲池的比例。同时,也可以指定配置哪些写操作启用写缓冲,可以设置成all/none/inserts/deletes等;

4、Change Buffer不会出现数据不一致的情况,原因有二:

  • 数据库异常奔溃,能够从redo log中恢复数据;
  • 写缓冲不只是一个内存结构,它也会被定期刷盘到写缓冲系统表空间。

今天主要讲解了MySQL InnoDB Change Buffer的工作原理,通过一些例子来说明整个过程,偏理论的知识,大家理解记忆即可,面试中也可能会被问到。站在巨人的肩膀上,每天进步一点点!~

end

文章转载自 GrowthDBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论