自学内容网 自学内容网

一文了解MySQL写缓冲Change Buffer(定义 作用 执行过程 触发时机 业务场景)

MySQL的数据存储包含内存与磁盘两个部分,内存缓冲区buffer pool以页为单位,缓存最热的数据页data page与索引页index page,InnoDB以变种LRU算法管理缓冲池,并且解决了预读失效和缓冲池污染的问题。对于读请求,缓冲池可以减少磁盘IO,提升性能,那么写请求呢?

思考2个场景:

场景1:假设要修改页号为4的索引页,这个页恰好在缓冲池里,那么修改的步骤为:

  • 直接修改缓冲池的页,一次内存操作
  • 写入redo log,一次磁盘顺序写操作

这样效率高,而且写日志这种顺序写,每秒可以支持上万的并发量

一致性问题也不会出现,如果读取的时候,命中缓冲池的页;缓冲池通过LRU后淘汰了数据,会将正确数据刷回磁盘;数据库异常崩溃,redo log里恢复的数据也没问题。

那么缓冲池的页什么时候会刷到磁盘上呢?定期刷磁盘,通过批量写的方式降低磁盘IO

场景2:修改页号为100的索引页,这个页不在缓冲池里,修改的步骤为:

  • 先把序号为100的索引页从磁盘加入到缓冲池里,一次磁盘随机读操作
  • 修改缓冲池的页,一次内存操作
  • 写入redo log,一次磁盘顺序写操作

没有命中缓冲池的时候,至少产生一次磁盘IO,对于写多读少的业务场景,还有优化的空间,也就是写缓冲 change buffer,是降低磁盘IO,提升数据库写性能的一种机制。

定义和作用

写缓冲Change Buffer是InnoDB为了提高非主键索引操作性能而引入的一种机制。当对非唯一索引进行更改(如插入、更新、删除操作)时,如果对应的数据页不在缓冲池(Buffer Pool)中,InnoDB不会立即从磁盘读取数据页,而是将这些更改操作缓存到Change Buffer中,等未来数据被读取时,再将数据合并merge恢复到缓冲池中。这样做的目的是为了减少对磁盘的I/O操作,从而提高数据库的整体性能。

执行过程

还是以刚刚的场景2为例,修改页号为100的索引页,这个页不在缓冲池里,加入写缓冲后修改的步骤为:

  • 在写缓冲里记录这个操作,一次内存操作
  • 写入redo log,一次磁盘顺序写操作

性能与 场景1相近

对于数据一致性问题,也不会出现。数据库异常崩溃的时候,可以从redo log里恢复数据;写缓冲也会被定期刷盘到写缓冲系统表空间;数据读取的时候,将数据合并到缓冲池。

当稍后有请求查询索引页100的数据时,流程如下:

  • 缓冲池未命中,从磁盘里载入索引页
  • 从写缓冲读取相关信息
  • 恢复索引页,放入缓冲池

整个写缓冲的执行过程可以总结如下:

  1. 更改暂存:非主键索引的记录被更新或删除时,这些更改操作首先被暂存到Change Buffer中
  2. 合并更改:当数据页从磁盘上读取到内存中时,Change Buffer中的相关信息会被用来合并这些更改,即应用到对应的缓存数据页中。
  3. 刷新到磁盘:Change Buffer中的更改操作最终会被刷新到磁盘上,以保持数据的一致性。
  4. 清理过程:InnoDB会定期执行清理过程,移除那些已经过时或不再需要的更改操作信息。

触发时机

  1. 非主键索引的更新操作:当一个非主键索引的记录被更新时,Change Buffer会触发并将更改操作暂存到内存中
  2. 非主键索引的删除操作:当一个非主键索引的记录被删除时,Change Buffer同样会触发并将该删除操作暂存到内存中。
  3. 数据页读取操作:当从非主键索引页读取数据时,Change Buffer会检查该页是否在Change Buffer中有相关的更改。如果有,它会将这些更改应用到该页上,确保读取的数据是最新的。

思考一个问题:为什么写缓冲优化,只适用于二级索引?

如果索引设置了唯一unique属性,在修改操作时,InnnoDB必须进行唯一性检查。索引页即使不在缓冲池里,磁盘上的页读取也是要进行的,因为要检验是否唯一,这里就会把相应的页直接放入缓冲池再修改,无需写缓冲。

刷数据时机

上面提到了如果数据页被访问,写缓冲的数据就会被刷新,除此之外,还有下面几种场景:

  • 后台线程认为数据库空闲时
  • 数据库缓冲池不够用
  • 数据库正常关闭
  • redo log写满 (这时整个数据库都处于无法写入的不可用状态)

优缺点

优点:减少随机磁盘I/O,提高写入操作的性能,特别是对于写密集型操作。

缺点:仅适用于非唯一普通索引页,且在随机读负载时效果可能不佳。

业务场景

不适合的业务场景:

  • 数据库都是唯一索引
  • 写入数据后立刻读取:因为写操作进行后,本来就要立刻进行页读取,需要从磁盘里将这个页面载入缓冲池,这时还用写缓冲多此一举

适合的业务场景:

  • 数据库大部分是非唯一索引
  • 业务写多读少,或是 写入数据后不会立刻读取

配置

innodb_change_buffer_max_size:配置写缓冲的大小占整个缓冲区的比例,默认25%,最大50%

innodb_change_buffering:配置哪些写操作启用写缓冲,取值为all/none/inserts/deletes

  • Change Buffer中包含的操作主要有三种:插入缓冲(Insert Buffer)、删除缓冲(Delete Buffer)和更新缓冲(Update Buffer)

对比

写缓冲与Redo Log的关系: 写缓冲用于暂存对二级索引页的修改,而Redo Log记录了对数据的所有修改操作,包括主键索引和二级索引,以保证数据的持久性和一致性


原文地址:https://blog.csdn.net/LightOfNight/article/details/144302048

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!