上一篇:Mysql——InnoDB存储引擎Checkpoint
简介
变更缓冲区(原来的Insert Buffer)是一种特殊的数据结构,存储位置在:
- 缓冲池;
- 磁盘的系统表空间;
大多数场景,辅助索引页的访问都会造成随机的IO,相对顺序IO来讲效率非常差,对于辅助索引数据的INSERT,UPDATE或DELETE操作,对辅助索引操作来说,性能影响很大。需要去磁盘扫描辅助索引,数据量大的时候通常会有多次的随机IO,才找到对应辅助索引页。因此Change Buffer正是来解决这个问题的。
Change Buffer工作原理
辅助索引数据的INSERT,UPDATE或DELETE操作,innoDB首先判断辅助索引的页是否在缓冲池中,如果在,则直接操作;如果不在,则先放到缓冲池的Change Buffer中,然后通过后台线程按照一定的频率和情况进行Change Buffer和辅助索引页的merge(合并)操作,通常能将多次的操作合并成一次操作(一个索引页包含多个索引数据),这就大大提高了辅助索引数据操作的性能,可以通过
innodb_change_buffer_max_size
调整变更缓冲大小,默认是25,最大只能设置为50,按照百分比取值。
Change Buffer的使用需要满足以下两个条件:
- 索引是辅助索引;
- 索引不是唯一的;
当满足以上两个条件的时候,InnoDB会使用Change Buffer,这样就能提高DML操作性能。当然该机制也有一定的弊端:比如,大量的DML操作导致大量的Change Buffer没有合并到辅助索引页中,如果发生了宕机,重启恢复需要很长的时间。
考虑一个问题,为什么Change Buffer规定索引不是唯一的?
答案很明显,Change Buffer设计的初衷就是为了减少磁盘随机IO,如果是唯一索引,需要多一步索引唯一性校验
是需要访问磁盘的,如果是这样就会失去了意义。
Change Buffer数据结构
Change Buffer的数据结构实际上是一颗B+ Tree,由所有表进行Change Buffer的非唯一辅助索引组成。
B+ Tree每个节点存储内容如下:
space | marker | offset | metadata | secondary index record |
---|---|---|---|---|
表空间id 占用4个字节 | 区分新老版本 占用1个字节 | 索引页偏移量,即page_no 占用4个字节 | 元数据 占用4个字节 | 辅助索引记录 |
metadata存储内容如下:
IBUF_REC_OFFECT_COUNT | IBUF_REC_OFFECT_TYPE | IBUF_REC_OFFECT_FLAGS |
---|---|---|
用来排序每个记录进入Change Buffer的顺序 占用2个字节 | 对用缓存的操作类型 占用1个字节 | 表示行格式 占用1个字节 |
为了保证每次都能merge成功,还需要有一个特殊的页来标记每个辅助索引页(space,page_no)的可用空间。这个就是Insert Buffer Bitmap,每个Insert Buffer Bitmap页用来追踪16384个辅助索引页。每个辅助索引页在Insert Buffer Bitmap存储结构如下:
IBUF_BITMAP_FREE | IBUF_BITMAP_BUFFERED | IBUF_BITMAP_IBUF |
---|---|---|
表示该辅助索引页的可用空间(占用2个bit): 0 表示无可用空间 1 表示剩余空间>1/32 2 表示剩余空间>1/16 3 表示剩余空间>1/8 | 1 表示该辅助索引页有记录被缓存到Change Buffer中(占用1个bit) | 1 表示该页是Change Buffer B+ Tree的页 |
Change Buffer工作状态
可以通过SHOW ENGINE INNODB STATUS;
查看Change Buffer工作状态:
如上图所示,首先看下Ibuf那一行:
- size:表示已经合并到辅助索引页的数量;
- free list len:表示空闲列表长度;
- seg size:表示当前Change Buffer的大小,2*16KB;
- merges:表示合并的次数;
- merged operations:表示每个具体操作合并的次数;
- insert:表示插入操作;
- delete mark:表示删除标记操作;
- delete:表示物理删除操作;
- discarded operations:表示操作的表已经被删除,不需要合并的每个具体操作次数;
InnoDB提供了innodb_change_buffering
配置,可选值如下:
选项 | 说明 |
---|---|
inserts | 插入缓冲; |
deletes | 删除标记缓冲; |
changes | 更新缓冲,由两个上面inserts、deletes组成; |
purges | 缓冲在后台发生的物理删除操作; |
all | 表示启用上面所有; |
none | 表示什么都不启用; |
Change Buffer合并操作触发
- 辅助索引页被读取到缓冲池:
当辅助索引页被读取到缓冲池时,需要检查Insert Buffer Bitmap页IBUF_BITMAP_BUFFERED==1
?如果是,则触发合并操作; - Insert Buffer Bitmap页追踪到改辅助索引页无可用空间时:
插入辅助索引页时,检测到此次插入后的辅助索引页大小会<1/32,就会强制触发合并操作; - Master Thread:每秒或每10秒触发一次合并操作;在Change Buffer B+ Tree中,树的节点根据(space, offset)排序。Master Thread会随机选择Change Buffer B+ Tree的一个节点,读取从该节点开始到之后所需要的节点数量。比如Master Thread合并变更缓存的数量=5,那么就随机选择一个节点,从该节点之后的5个节点(包括第一个选中的节点)。