一 插入缓冲
1.1 解决的问题
插入多条数据时,除了需要插入聚集索引外,还需要插入到非聚集索引中,然而非聚集索引的插入走的是随机写,这个操作会影响性能。
1.2 基本原理
插入非聚集索引时,不会直接写到真正的非聚集索引里面去,而是先写到一个叫插入缓冲
的临时文件中(注意插入缓冲虽然名字叫缓冲,实际上是临时文件)
然后依赖后台线程将插入缓冲中的内容更新到真正的非聚集索引上去。
由于对插入缓冲的写是连续的,所以这种操作就解决了随机写的问题。
1.3 使用条件
并不是所有对非聚集索引的更新都会使用插入缓冲,需要满足以下两个条件:
- 非聚集索引不是唯一的
- 要插入的非聚集索引页不在内存中
为什么不能是唯一索引的?
因为如果是唯一索引,则插入的时候就需要判断是否有重复,而这个判断的过程本身就包含一次随机读,所以即使使用了插入缓冲也无法解决磁盘随机读写的问题
为什么非聚集索引页不能在内存中?
其实并不是非聚集索引页不能在内存中,而是在内存中的非聚集索引页就不需要走插入缓冲了。因为如果在内存中的话,那直接写内存中的缓存页即可。
这里可能还会有疑问,写了内存中的缓存页后,把缓存页刷新到磁盘时不是也会随机写磁盘吗?
其实不是的,内存中的缓存页被更新后不会立即刷新到磁盘中,而是等待后台线程刷新。所以这里也不会随机读写磁盘。
可能还会有疑问,如果内存中的缓存页被更新后不直接刷新到磁盘,那么宕机时岂不是会丢失数据吗?
其实这里也不会,因为在写内存中的缓存页时会先写重做日志,记录更新的内容,而这个重做日志是会在事务提交前就刷新到磁盘中的,所以即使宕机,也可以用重做日志恢复数据。另外重做日志也是磁盘上连续的空间,所以也不会有随机读写
二 两次写
2.1 解决的问题
当数据库写物理页时,如果宕机了,那么可能会导致物理页的一致性被破坏。
可能有人会说,重做日志不是可以恢复物理页吗?实际上是的,但是要求是在物理页一致的情况下。
也就是说,如果物理页完全是未写之前的状态,则可以用重做日志恢复。如果物理页已经完全写完了,那么也可以用重做日志恢复。但是如果物理页前面2K写了新的数据,但是后面2K还是旧的数据,则种情况下就无法使用重做日志恢复了。
这里的两次写就是保证了物理页的一致性,使得即使宕机,也可以用重做日志恢复。
2.2 基本原理
在写物理页时,并不是直接写到真正的物理写上去,而是先写到一个临时页上去,临时页写完后,再写物理页。
这样一来:
- 如果写临时页时宕机了,物理页还是完全未写之前的状态,可以用重做日志恢复
- 如果写物理页时宕机了,则可以使用临时页来恢复物理页
2.3 具体实现
- InnoDB中共享表空间中划了2M的空间,叫做double write,专门存放临时页。
- InnoDB还从内存中划出了2M的缓存空间,叫做double write buffer,专门缓存临时页
- 每次写物理页时,先写到double write buffer中,然后从double write buffer写到double write上去。最后再从double write buffer写到物理页上去
你问我为什么要有 double write buffer
这个东西?其实吧InnoDB里面物理页都 会有内存缓存。只是这里单把这2M的缓存取了个名字而已。
三 自适应哈希索引
InnoDB自动监控对索引的查找,如果发现建立哈希索引可以提高效率,则会自动建立
可以使用innodb_adaptive_hash_index来启用或者关闭,默认是开启的