InnoDB特性—变更缓冲change buffer

一、简介

change buffer是InnoDB存储引擎的一个重要特性,但在InnoDB 1.0.x版本之前,只支持插入缓冲(insert buffer),后来又对其进行升级,不仅支持insert buffer,还支持delete、update的缓冲,分别对应delete buffer、purge buffer,并统称为变更缓冲(change buffer)。

  • 结构:change buffer数据结构是一颗B+树;
  • 存储:位于缓冲池(buffer pool)中,存储在共享的表空间,默认是iddata1系统表空间,既拷贝在内存,也存储在磁盘;
  • 作用:当有数据变更操作时,如果数据页也不在内存中,在不影响数据一致性的前提下,InnoDB存储引擎会先将变更操作写入change buffer中,当下一次查询需要访问这个数据页(原数据页)时,再执行change buffer中缓存的变更操作,得到变更后的数据页(通过执行change buffer中的缓存的变更操作,将原数据页进行变更,得到变更后的数据页,这个过程称为merge)。change buffer有效的减少了读磁盘的次数,也减少了数据页占用缓冲池(buffer pool)的内存,提高内存的利用率;
  • 使用条件:数据的变更操作只能包含普通索引,不能包含唯一索引。
    在这里插入图片描述

二、内部实现

接下来将以change buffer中的insert buffer为例来介绍其内部实现。

insert buffer的结构

insert buffer的数据结构是一颗B+树,由叶子节点和非叶子节点组成。
非叶子节点存储着键值(search key),search key共占9个字节,其结构如下:
在这里插入图片描述

  • space(占4字节):待变更记录所在表的表空间id,每个表有唯一的space id,通过space id可查找到具体的表;
  • marker(占1字节):用于兼容老版本的insert buffer;
  • offset(占4字节):页偏移量;

叶子节点存储着记录,其结构如下:
在这里插入图片描述

  • 前三个字段与非叶子节点含义相同,占9字节;
  • metadata(占4字节):通过记录进入insert buffer的顺序;
  • 其余的则是存储着插入的记录;

merge insert buffer

触发merge insert buffer的三种情况:

  • 发生了,将数据页从磁盘读到内存:如insert buffer中有数据“A”的插入缓冲记录,当下次查询数据“A”时,就会触发merge;
  • 普通索引页空间不足:当有插入操作请求到来时,insert buffer bitmap检测到插入该变更后,可用空间小于1/32页,就会强制出发merge;
  • 主线程(master thread)触发:每秒或没十秒会进行一次merge。

三、案例分析

change buffer是怎么减少随机IO访问的?

insert into T (user_id,name) values(23,"张三");

假设需要向表T插入如上的数据,则更新的过程如下:

  • 情景一:插入的数据在数据页中
    若user_id为唯一索引:找到user_id为22和24之间的位置,判断没有冲突,则插入数据;
    若user_id为普通索引:找到user_id为22和24之间的位置,插入数据;
  • 情景二:插入的数据不在数据页中
    若user_id为唯一索引:将数据从磁盘读到内存,找到user_id为22和24之间的位置,判断没有冲突,则插入数据;
    若user_id为普通索引:将数据更新到change buffer;

从中可以看出,普通索引场景下,change buffer可以减少磁盘读入内存随机IO的访问,对更新性能有明显的提升。

是不是普通索引场景下,使用change buffer就可以提升更新性能?
普通索引场景下,使用change buffer不一定就可以提升更新性能!

  • 读多写少的业务:当更新执行后,不会立马触发查询,即查询频率很低的情况下,触发merge的频率就会很低;
  • 读少写多的业务:当更新执行后,就会立马触发查询,即立即出发merge,此时随机访问IO的次数不会减少,还会增加change buffer的维护代价。

故change buffer使用于,写多读少的业务,如日志类系统。

将普通索引改为唯一索引,系统都组塞了?
对于读多写少的业务,使用了change buffer,若要将普通索引改为唯一索引,即使代码层面保证了满足唯一的原则,依旧存在着很大的风险,QPS很高时,可能会导致频繁的merge,随机访问IO的次数增加,进而导致系统阻塞!

通过ibd文件恢复表数据时,CHECK TABLE失败了?
如果直接通过ibd文件恢复表数据,往往会导致CHECK TABLE失败。因change buffer中还存在变更缓冲,需要通过REPAIR TABLE来重建普通索引。


参考
[1] MySQL官方文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-change-buffer.html
[2] 《MySQL实战45讲》:https://time.geekbang.org/column/article/70848
[3] 《MySQL技术内幕:InnoDB存储引擎》
[4] 《高性能MySQL》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值