一文了解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的数据时,流程如下:
- 缓冲池未命中,从磁盘里载入索引页
- 从写缓冲读取相关信息
- 恢复索引页,放入缓冲池
整个写缓冲的执行过程可以总结如下:
- 更改暂存:非主键索引的记录被更新或删除时,这些更改操作首先被暂存到Change Buffer中
- 合并更改:当数据页从磁盘上读取到内存中时,Change Buffer中的相关信息会被用来合并这些更改,即应用到对应的缓存数据页中。
- 刷新到磁盘:Change Buffer中的更改操作最终会被刷新到磁盘上,以保持数据的一致性。
- 清理过程:InnoDB会定期执行清理过程,移除那些已经过时或不再需要的更改操作信息。
触发时机
- 非主键索引的更新操作:当一个非主键索引的记录被更新时,Change Buffer会触发并将更改操作暂存到内存中
- 非主键索引的删除操作:当一个非主键索引的记录被删除时,Change Buffer同样会触发并将该删除操作暂存到内存中。
- 数据页读取操作:当从非主键索引页读取数据时,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)!