你插入MySQL的数据真的存到表里了么?

你插入MySQL的数据真的存到表里了么?

如今有这么一个问题:当你执行一条insert语句以后,插入的数据就已经保存在磁盘中了么?mysql

答案是不必定 ,那是为何呢?首先来了解一下MySQL在InnoDB存储引擎中,数据是怎么存储的。sql

1. InnoDB数据存储单元

同大多数数据库同样,InnoDB有页(Page)的概念(也能够称为块),页是InnoDB磁盘管理的最小单位。在InnoDB存储引擎中,默认每一个页的大小为16 KB。而从InnoDB 1.2.x版本开始,能够经过参数InnoDB_page_size将页的大小设置为4 K、8 K、16 K。若设置完成,则全部表中页的大小都为InnoDB_page_size,不能够对其再次进行修改。除非经过mysqldump导入和导出操做来产生新的库。数据库

file

InnoDB的数据是按数据页为单位来读写的。也就是说,当须要读一条记录的时候,并非将这个记录自己从磁盘读出来,而是以页为单位,将其总体读入内存。缓存

而将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操做之一,因此为了减小磁盘IO,InnoDB设计了change buffer这个机制。函数

2. change buffer

在MySQL 5.5以前的版本中,因为只支持缓存insert操做,因此最初叫作insert buffer,只是后来的版本中支持了更多的操做类型缓存,才改叫change buffer,这也是为何代码中有大量的ibuf前缀开头的函数或变量。性能

然而使用change buffer须要同时知足两个条件:spa

(1) 索引是辅助索引

插入聚簇索引通常是顺序的,通常不须要磁盘的随机读取,因此不须要使用change buffer线程

(2) 索引不是惟一的设计

辅助索引不能是惟一的,由于在插入缓冲时,数据库并不去查找索引页来判断插入的记录的惟一性。若是去查找确定又会有离散读取的状况发生,从而致使change buffer失去了意义。日志

3. change buffer的底层实现

change buffer底层结构是一颗全局的B+树,负责对全部的表空间进行change buffer。

4. merge 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操做的页的数量不一样。

5. change buffer的使用场景

change buffer主要做用是将记录的变动缓存下来,merge的时候是真正进行数据更新的时刻,因此在一个数据页作merge以前,change buffer记录的变动越多(也就是这个页面上要更新的次数越多),收益就越大。

所以,对于写多读少的业务来讲,页面在写完之后立刻被访问到的几率比较小,此时change buffer的使用效果最好。这种业务模型常见的就是帐单类、日志类的系统。

相关文章
相关标签/搜索