Innodb的三大特性

插入缓冲(change buffer)、两次写(double write)、自适应哈希索引(adaptive hash index)

Insert Buffer是什么?

InnoDB 缓冲池包含了Insert Buffer的信息

但Insert Buffer 其实和数据页一样,也是物理存在的(以B+树的形式存在共享表空间中)。

工作原理

innodb_buffer_pool_instances和innodb_buffer_pool_size的比例_MySQL

把普通索引上的DML操作从随机IO变成顺序IO。

判断插入的普通索引页是否在缓冲池中,如果在直接插入,如果不在就要先放到change buffer中,然后进行change buffer

和普通索引的合并操作,可以将多个插入合并到一个操作中,提高普通索引的插入性能。

使用要求:

索引是非聚集索引

索引不是唯一(unique)的

只有满足上面两个必要条件时,InnoDB存储引擎才会使用Insert Buffer来提高插入性能。

自适应哈希索引(adaptive hash index)

innodb存储引擎有一个机制,可以监控索引的搜索,如果innodb注意到查询可以通过建立哈希索引得到优化,那么就可以自动完成这件事。可以通过innodb_adaptive_hash_index参数来控制。默认情况下是开启的。

两次写(double write)

InnoDB使用了一种叫做double write的特殊文件flush技术

1)在把pages写到data files之前,InnoDB先把它们写到一个叫doublewrite buffer的连续区域内

2)在写doublewrite buffer完成后,InnoDB才会把pages写到data file的适当的位置。

如果在写page的过程中发生意外崩溃,InnoDB在稍后的恢复过程中在doublewrite buffer中找到完好的page副本用于恢复。

partial page write问题

由于InnoDB和操作系统的页大小不一致,InnoDB页大小一般为16k,操作系统页大小为4k,导致InnoDB回写dirty数据到操作

系统中,一个页面需要写4次,写入过程出现问题无法保持原子性。写的过程如果崩溃或者断电,可能导致只有一部分写回

到操作系统文件系统中,整个数据只是部分成功,其实数据是损坏的。

redolog 不能解决吗?

redolog记录的是数据页的物理操作:对 XXX表空间中的XXX数据页XXX偏移量的地方做了XXX更新。如果页都损坏了,是

无法进行任何恢复操作的。所以我们需要页的一个副本,如果服务器宕机了,可以通过副本把原来的数据页还原回来。这就

是doublewrite的作用。

doublewrite buffer

双写缓冲位于系统表空间上,128个页(2个区)大小是2MB。

1)将脏数据复制到内存中的doublewrite buffer,之后通过doublewrite buffer再分2次,每次写入1MB到共享表空间,然后马

上调用fsync函数,同步到磁盘上,避免缓冲带来的问题,在这个过程中,doublewrite是顺序写,开销并不大

2)在完成doublewrite写入后,再将double write buffer写入各表空间文件,这时是离散写入。

所以在正常的情况下, MySQL写数据page时,会写两遍到磁盘上,第一遍是写到doublewrite buffer,第二遍是从doublewrite

buffer写到真正的数据文件中。

如果发生了极端情况(断电),InnoDB再次启动后,发现了一个page数据已经损坏,那么此时就可以从doublewrite buffer中进行数据恢复了。

doublewrite的缺点是什么?

位于共享表空间上的doublewrite buffer实际上也是一个文件,写共享表空间会导致系统有更多的fsync操作, 而硬盘的fsync性能因素会降低

MySQL的整体性能,但是并不会降低到原来的50%。这主要是因为:

doublewrite是在一个连续的存储空间, 所以硬盘在写数据的时候是顺序写,而不是随机写,这样性能更高。

将数据从doublewrite buffer写到真正的segment中的时候,系统会自动合并连接空间刷新的方式,每次可以刷新多个pages。

是否一定需要doublewrite

在一些情况下可以关闭doublewrite以获取更高的性能。比如在slave上可以关闭,因为即使出现了partial page write问题,数据还是可以从中继日志中恢复。设置InnoDB_doublewrite=0即可关闭doublewrite buffer。