InnoDB存储引擎关键特性简要介绍:插入缓冲、两次写、自适应哈希索引、异步IO、邻接页刷新

我们先来回顾下InnoDB整体结构:

InnoDB整体结构

InnoDB存储引擎由多个内存块和多个后台线程组成,其中:

  • 内存块包含三个部分:redo log_bufferinnodb_buffer_poolinnodb_additional_mem_pool_size
    在这里插入图片描述
    redo log_buffer用来缓存重做日志,innodb_additional_mem_pool_size一般用来缓存LRU、锁等数据结构。
    innodb_buffer_pool缓冲池,包含了数据页、索引页、undo页、插入缓冲、锁信息、自适应哈希索引和数据字典。其中数据页和索引页占据了缓冲池很大一部分空间。缓冲池通过内存快速的读写性能来弥补磁盘的IO以提高数据库的性能。

  • 后台线程类型有:Master ThreadIO ThreadPurge ThreadPage Cleaner Thread
    Master Thread是InnoDB存储引擎非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到硬盘,保证数据一致性,同时也负责脏页刷新、合并插入缓冲、undo页回收。
    IO Thread负责处理IO回调,分为4种类型:writereadinsert bufferlog IO Thread,Windows系统可以自定义readwrite线程的数量,Linux则不可以。
    Purge Thread用于在事务提交后,回收已经使用并分配的undo页,该线程在一个MySQL进程中只可有1个。
    Page Cleaner Thread用来处理缓冲池中脏页的刷新操作,以减轻Master Thread负担。

关键特性

InnoDB存储引擎包含了以下几个关键特性

  • 插入缓冲(Insert Buffer)
  • 两次写(double write)
  • 自适应哈希索引(Adaptive Hash Index
  • 异步IO(AIO)
  • 刷新领接页
插入缓冲(Insert Buffer)

Insert Buffer不仅仅是缓冲池的一部分,它和数据页一样也是物理页的组成部分。Insert Buffer是为了增加非唯一(Unique)、非聚集索引的插入或更新操作的性能。

InnoDB存储引擎的表中主键(属于聚集索引)是行的唯一标识符,一般行记录的插入时按照主键递增的顺序插入的,并且,InnoDB存储数据时,将主键和数据通过聚簇索引的方式存储在一个文件中,无需硬盘进行随机读写:
在这里插入图片描述
很多情况下,一张表上可能有多个非聚集辅助BTREE索引,辅助索引叶子节点的插入不再是顺序的了,这时就需要对这个BTREE进行随机访问,导致插入性能下降。所以,Insert Buffer也就随之诞生了。

Insert Buffer在执行非聚集索引的插入操作时并不会每次都插入到索引页中,它会首先判断非聚集索引页是否在缓冲池中,如果在就直接插入,如果不在就先放入一个Insert Buffer对象中,然后以一定的频率和具体情况进行Insert Buffer和辅助索引页子节点进行合并操作,从而将多个插入操作合并为一个插入操作(也就是将多次随机IO缩减为一次),大大增加了非聚集索引的插入性能。

除了Insert Buffer,InnoDB还有Delete BufferPurge Buffer,它们都属于Change Buffer的范畴,可以对所有DML操作进行缓冲。将一个记录进行修改操作包含两个步骤:

  1. 将记录标记为已删除
  2. 真正将记录删除

Delete Buffer进行第一个过程,Purge Buffer进行第二个过程。

两次写(doublewrite)

InnoDB两次写的特性带来的数据页的可靠性。例如:当InnoDB正在将某个页写入到表文件中,此时数据库宕机导致这个页只写了一半到表文件(称之为部分写失效),在没有两次写技术前,就有可能因为这个导致数据丢失。需要注意的是,对于部分写失效,是无法通过重做日志来恢复的,因为重做日志记录的是页的物理操作,如果这个页本身发生了损坏对其进行重做是没有用的。

所以,在应用重做日志前,需要一个原页面的拷贝,当写入失效发生时,就可以通过这个拷贝来恢复这个页,再进行重做,这就是doublewrite所做的事。

doublewrite有两部分组成:

  1. 内存中的doublewrite buffer,大小为2MB
  2. 物理磁盘共享表空间连续128个页(即2个区),大小为2MB

在对缓冲池脏页进行刷新时,首先会将脏页复制到内存的doublewrite buffer,之后通过doublewrite buffer再分两次,每次1MB,顺序地写入到共享表空间的物理硬盘上,然后调用fsync函数同步磁盘,避免缓冲写带来的问题,由于doublewrite页是连续的,因此这个过程是顺序的。在完成doublewrite页的写入后,再将doublewrite buffer中的页写入到各个表空间文件(ibd)中,此时写入是离散的。

在这里插入图片描述

自适应哈希索引

一般情况下,哈希查找的时间复杂度为O(1),仅需要1次就能定位到数据,而对于B+树一般高度为3至4层,需要3~4次查询。InnoDB为了能够利用到哈希索引所带来的查询性能优势,会监控表上各个索引页的查询,如果建立哈希索引可以带来速度提升,则建立哈希索引,这种操作称之为自适应哈希索引

自适应哈希索引通过缓冲池中的B+树页构造而来,因此建立的速度很快,无需对整张表构建哈希索引,只需要根据热点页建立。

自适应哈希索引的构造有以下几个原则:

  1. 索引页的连续访问模式必须是一样的,对于(a,b)这样的联合索引页,其访问模式有WHERE a=xxx或者是WHERE a=xxx and b=xxx。如果上述两个访问模式都经常使用,那么不会对这个索引页构造自适应哈希索引。
  2. 以上述访问模式访问了100次
  3. 页通过该模式访问了N次,N等于页中记录除以16

通过自适应哈希索引,读取和写入速度可以提高2倍,辅助索引的连接操作性能可以提高5倍。

异步IO

为了提高磁盘的操作性能,InnoDB采用了异步IO(AIO)来处理其磁盘操作,以解决同步IO在进行IO操作时需要等待操作结束才能继续后续流程的缺陷。

在InnoDB执行SQL语句时,可能需要扫描多个索引页,也就是需要执行多个IO操作,这就会造成后一个IO操作的执行必须要等待前一个IO操作完成所造成时间开销过大的问题,而AIO可以提交多个IO操作,并等待所有IO操作的完成。此外,AIO还可以进行IO Merge操作,也就是将多个IO操作合并为1个,这样可以提高性能。

InnoDB的AIO基于操作系统的内核实现,所以需要操作系统能够支持AIO,Windows和Linux均支持AIO,而Mac OS未提供支持。

刷新邻接页

InnoDB存储引擎还提供了刷新邻接页(Flush Neighbor Page)的特性:
当刷新一个脏页时,InnoDB会检测该页所属区的所有页,如果是脏页那么就一起刷新,这种方式可以利用AIO将多个IO操作合并为一个IO操作,如果硬盘属于机械硬盘,那么会有显著的性能提升,对于SSD而言则没有必要,可以通过参数innodb_flush_neighbors设为0来关闭此项功能。

参考资料:《MySQL技术内幕——InnoDB存储引擎》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值