如今有这么一个问题:当你执行一条insert语句以后,插入的数据就已经保存在磁盘中了么?mysql
答案是不必定 ,那是为何呢?首先来了解一下MySQL在InnoDB存储引擎中,数据是怎么存储的。sql
同大多数数据库同样,InnoDB有页(Page)的概念(也能够称为块),页是InnoDB磁盘管理的最小单位。在InnoDB存储引擎中,默认每一个页的大小为16 KB。而从InnoDB 1.2.x版本开始,能够经过参数InnoDB_page_size
将页的大小设置为4 K、8 K、16 K。若设置完成,则全部表中页的大小都为InnoDB_page_size
,不能够对其再次进行修改。除非经过mysqldump
导入和导出操做来产生新的库。数据库
InnoDB的数据是按数据页为单位来读写的。也就是说,当须要读一条记录的时候,并非将这个记录自己从磁盘读出来,而是以页为单位,将其总体读入内存。缓存
而将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操做之一,因此为了减小磁盘IO,InnoDB设计了change buffer
这个机制。函数
在MySQL 5.5以前的版本中,因为只支持缓存insert操做,因此最初叫作insert buffer
,只是后来的版本中支持了更多的操做类型缓存,才改叫change buffer
,这也是为何代码中有大量的ibuf前缀开头的函数或变量。性能
然而使用change buffer
须要同时知足两个条件:spa
(1) 索引是辅助索引插入聚簇索引通常是顺序的,通常不须要磁盘的随机读取,因此不须要使用change buffer线程
(2) 索引不是惟一的设计
辅助索引不能是惟一的,由于在插入缓冲时,数据库并不去查找索引页来判断插入的记录的惟一性。若是去查找确定又会有离散读取的状况发生,从而致使change buffer失去了意义。日志
change buffer
底层结构是一颗全局的B+树,负责对全部的表空间进行change buffer。
从上文可知Change Buffer
是一棵B+树。当须要实现插入记录的辅助索引页不在缓冲池中,辅助索引记录首先会插入到这棵B+树中。那么Insert Buffer
中的记录什么时候合并(merge)到真正的辅助索引中呢?
merge操做可能发生在如下几种状况下
Change buffer bitmap
页追踪到的辅助页已无可用空间master thread
第一种状况为当辅助索引页被读取到缓冲池中时,例如这在执行正常的SELECT查询操做,这时须要检查Insert Buffer Bitmap
页,而后确认该辅助索引页是否有记录存放于Insert Buffer
B+树中。如有,则将Insert Buffer
B+树中该页的记录插入到该辅助索引页中。对该页屡次的记录操做经过几回操做合并到了原有的辅助索引页中,所以性能会有大幅提升。
第二种状况Insert Buffer Bitmap
页用来追踪每一个辅助索引页的可用空间,并至少有1/32页的空间。若插入辅助索引记录时检测到插入记录后可用空间会小于1/32页,则会强制进行一个合并操做,即强制读取辅助索引页,将Insert Buffer B+树中该页的记录及待插入的记录插入到辅助索引页中。这就是上述所说的第二种状况。
第三种状况就是在Master Thread
线程中每秒或每10秒会进行一次Merge Change Buffer
的操做,不一样之处在于根据线程的工做状态每次进行merge
操做的页的数量不一样。
change buffer
主要做用是将记录的变动缓存下来,merge的时候是真正进行数据更新的时刻,因此在一个数据页作merge
以前,change buffer
记录的变动越多(也就是这个页面上要更新的次数越多),收益就越大。
所以,对于写多读少的业务来讲,页面在写完之后立刻被访问到的几率比较小,此时change buffer
的使用效果最好。这种业务模型常见的就是帐单类、日志类的系统。