InnoDB Insert Buffer(插入缓冲)数据库
每一个存储存储引擎自身都有本身的特性(决定性能以及更高可靠性),而InnoDB的关键特性有:缓存
今天主要聊一下插入缓冲(Insert Buffer)在InnoDB存储引擎中的做用。异步
Insert Buffer实际上是一种重要的数据变动日志,在MySQL5.1 以前称为Insert Buffer, 优化2级非惟一索引上插入操做的读IO,在MySQL5.5以后更名为Change Buffer, 功能也扩展为2级非惟一索引上的插入、删除、更新、purge的读IO优化。也就是说Change buffer的主要目的是将对二级索引的数据操做缓存下来,以此减小二级索引的随机IO,并达到操做合并的效果。值得提的一点是,Change Buffer也是物理页的组成部分。性能
struct ibuf_struct{ ulint size; //当前ibuf btree 页面数 ulint max_size; //ibuf最大页面数 ulint seg_size; //所属段的页面数 ibool empty; //是否为空 ulint free_list_len; //空闲链表长度 ulint height; //树高度 dict_index_t* index; //ibuf索引 ulint n_merges; //合并的页面数 ulint n_merged_ops[IBUF_OP_COUNT]; //各类操做合并的页面数 ulint n_discarded_ops[IBUF_OP_COUNT]; //放弃的操做涉及的页面数 };
从上述的结构体能够得知,Ibuf实际上也是一棵B+树索引,它与innodb中其余的b+树有着彻底同样的结构。Ibuf树中的记录其实就是包含了记录自己,还有记录所在页面号的信息。优化
值得注意的点是,ibuf只适用于 non-unique secondary indexes 也就是说只能用在非惟一的索引上,缘由以下:spa
1. primary key 是按照递增的顺序进行插入的,异常插入聚族索引通常也顺序的,非随机IO线程
2. 写惟一索引要检查记录是否是存在,因此在修改惟一索引以前,必须把修改的记录相关的索引页读出来才知道是否是惟1、这样ibuf就没意义了,要读出来(随机IO)因此只对非惟一索引有意义。日志
ibuf能够对三种类型的操做进行缓存:INSERT、DELETE-MARK 、DELETE操做,前两种对应用户线程操做,第三种则由purge操做触发。code
用户能够经过参数innodb_change_buffering来控制缓存何种操做:blog
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = { "none", /* IBUF_USE_NONE */ "inserts", /* IBUF_USE_INSERT */ "deletes", /* IBUF_USE_DELETE_MARK */ "changes", /* IBUF_USE_INSERT_DELETE_MARK */ "purges", /* IBUF_USE_DELETE */ "all" /* IBUF_USE_ALL */ };
ibuf默认值为all,表示缓存全部操做。注意因为在二级索引上的更新操做老是先delete-mark,再insert新记录,所以update会产生两条ibuf entry。
所以delete buffer对应update操做的第一个过程,即将记录标记为删除。purge buffer对应update操做的第二个过程,即将记录真正的删除。同时InnoDB存储引擎提供了参数innodb_change_buffering,用来开启各类buffer选项。该参数的可选值为:inserts、deletes、purges、changes、all、none。inserts、deletes、purges就是前面讨论过的三种状况。changes表示启用inserts和deletes,all表示启用全部,none表示都不启用。