MySQL存储引擎之InnoDB - 写缓冲(change buffer)

1、前序1


《MySQL存储引擎之InnoDB - 缓冲池(buffer pool)》中提到:
(1)MySQL数据存储包含内存磁盘两个部分;
(2)内存缓冲池(buffer pool)以页为单位,缓存最热的数据页(data page)与索引页(index page);
(3)InnoDB以变种LRU算法管理缓冲池,并能够解决【预读失效】与【缓冲池污染】的问题;

在这里插入图片描述
毫无疑问,对于读请求,缓冲池能够减少磁盘IO,提升性能。问题来了,那写请求呢?

2、场景1:访问页命中缓冲池


假如要修改页号为4的索引页,而这个页正好在缓冲池内。

在这里插入图片描述
如上图:
(1)直接修改缓冲池中的页,一次内存操作;
(2)写入redo log,一次磁盘顺序写操作;
这样的效率是最高的。像写日志这种顺序写,每秒几万次没问题。

  • 数据一致性问题(不存在)
    (1)读取,会命中缓冲池的页;
    (2)缓冲池LRU数据淘汰,会将“脏页”刷回磁盘;
    (3)数据库异常奔溃,能够从redo log中恢复数据;
  • 缓冲池中的页刷新到磁盘的时机
    定期刷磁盘,而不是每次刷磁盘。能够降低磁盘IO,提升MySQL的性能。(批量写,是常见的优化手段)

3、场景2:访问页未命中缓冲池


假如要修改页号为40的索引页,而这个页正好不在缓冲池内。

在这里插入图片描述
此时麻烦一点,如上图需要1-3:
(1)先把页号为40的索引页,从磁盘加载到缓冲池,一次磁盘随机读操作
(2)修改缓冲池中的页,一次内存操作
(3)写入redo log,一次磁盘顺序写操作
没有命中缓冲池的时候,至少产生一次磁盘IO,对于写多读少的业务场景,是否还有优化的空间呢?

4、写缓冲2


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

  • InnoDB加入写缓冲优化,上文“情况二”流程会有什么变化?
    假如要修改页号为40的索引页,而这个页正好不在缓冲池内。
    在这里插入图片描述
    加入写缓冲优化后,流程优化为:
    (1)在写缓冲中记录这个操作,一次内存操作;
    (2)写入redo log,一次磁盘顺序写操作;
    可以看到,40这一页并没有加载到缓冲池中。其性能与场景1相近。
    不妨设,稍后的一个时间,有请求查询索引页40的数据。
    在这里插入图片描述
    此时的流程如序号1-3:
    (1)载入索引页,缓冲池未命中,这次磁盘IO不可避免;
    (2)从写缓冲读取相关信息;
    (3)恢复索引页,放到缓冲池LRU里;
    可以看到,40这一页,在真正被读取时,才会被加载到缓冲池中。

  • 数据一致性问题(不存在)
    (1)数据库异常奔溃,能够从redo log中恢复数据;
    (2)写缓冲不只是一个内存结构,它也会被定期刷盘到写缓冲系统表空间;
    (3)数据读取时,有另外的流程,将数据合并到缓冲池;

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

  • 会刷写缓冲中的数据的几种情况
    (1)上文提到,数据页被访问的时候;
    (2)有一个后台线程,会认为数据库空闲时;
    (3)数据库缓冲池不够用时;
    (4)数据库正常关闭时;
    (5)redo log写满时(几乎不会出现,否则整个数据库处于无法写入的不可用状态);

5、写缓冲使用场景


  • 什么业务场景,不适合开启InnoDB的写缓冲机制?
    (1)数据库都是唯一索引;
    (2)或者,写入一个数据后,会立刻读取它;
    这两类场景,在写操作进行时(进行后),本来就要进行进行页读取,本来相应页面就要入缓冲池,此时写缓存反倒成了负担,增加了复杂度。

  • 什么业务场景,适合开启InnoDB的写缓冲机制?
    (1)数据库大部分是非唯一索引;
    (2)业务是写多读少,或者不是写后立刻读取;
    可以使用写缓冲,将原本每次写入都需要进行磁盘IO的SQL,优化定期批量写磁盘。例如:账单流水业务。

6、写缓冲参数配置


在这里插入图片描述

  • innodb_change_buffer_max_size
    配置写缓冲的大小,占整个缓冲池的比例,默认值是25%,最大值是50%。
    写多读少的业务,才需要调大这个值,读多写少的业务,25%其实也多了。
  • innodb_change_buffering
    配置哪些写操作启用写缓冲,可以设置成all/none/inserts/deletes等。

# 脚注


  1. 本文转载自博客《写缓冲(change buffer),这次彻底懂了!!》,并在学习的过程中对其进行了重新排版。 ↩︎

  2. 在MySQL5.5之前,叫插入缓冲(insert buffer),只针对insert做了优化;现在对delete和update也有效,叫做写缓冲(change buffer)。 ↩︎

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值