Mysql——InnoDB存储引擎Change Buffer

404 阅读4分钟

上一篇: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每个节点存储内容如下:

spacemarkeroffsetmetadatasecondary index record
表空间id
占用4个字节
区分新老版本
占用1个字节
索引页偏移量,即page_no
占用4个字节
元数据
占用4个字节
辅助索引记录

metadata存储内容如下:

IBUF_REC_OFFECT_COUNTIBUF_REC_OFFECT_TYPEIBUF_REC_OFFECT_FLAGS
用来排序每个记录进入Change Buffer的顺序
占用2个字节
对用缓存的操作类型
占用1个字节
表示行格式
占用1个字节

为了保证每次都能merge成功,还需要有一个特殊的页来标记每个辅助索引页(space,page_no)的可用空间。这个就是Insert Buffer Bitmap,每个Insert Buffer Bitmap页用来追踪16384个辅助索引页。每个辅助索引页在Insert Buffer Bitmap存储结构如下:

IBUF_BITMAP_FREEIBUF_BITMAP_BUFFEREDIBUF_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个节点(包括第一个选中的节点)。

下一篇:Mysql——InnoDB存储引擎doublewrite