面试相关:InnoDB重要特性

 

MySQL InnoDB通过如下重要特性实现了更好的新能和更高的特性

  • 插入缓冲(insert buffer)
  • 两次写(Double write)
  • 自适应哈希索引(adaptive hash index)
  • 异步io(Async IO)
  • 刷新领接页(Flush Neighbor Page)

 1 插入缓冲

1.1. 举个栗子
我们去图书馆还书,对应图书馆来说,他是做了insert(增加)操作,管理员在1小时内接受了100本书,这时候他有2种做法把还回来的书归位到书架上:
1)每还回来一本书,根据这本书的编码(书柜区-排-号)把书送回架上
2)暂时不做归位操作,先放到柜面上,等不忙的时候,再把这些书按照书柜区-排-号先排好,然后一次性归位
用方法1,管理员需要进出(IO)藏书区100次,不停的登高爬低完成图书归位操作,累死累活,效率很差。
用方法2,管理员只需要进出(IO)藏书区1次,对同一个位置的书,不管多少,都只要爬一次楼梯,大大减轻了管理员的工作量。
所以图书馆都是按照方法2来做还书动作的。但是你要说,我的图书馆就20本书,1个0.5米的架子,方法2和1管理起来都很方便,这种情况不在我们讨论的范围。当数据量非常小的时候,就不存在效率问题了。

关系数据库在处理插入操作的时候,处理的方法和上面类似,每一次插入都相当于还一本书,它也需要一个柜台来保存插入的数据,然后分类归档,在不忙的时候做批量的归位。这个柜台就是insert buffer.
这就是为什么会有insert buffer,更多的是处于性能优化的考虑。

1.2. 什么是插入缓冲
insert buffer是一种特殊的数据结构(B+ tree)并不是缓存的一部分,而是物理页。对于非聚集索引的插入或更新操作,不是每一次直接插入索引页.而是先判断插入的非聚集索引页是否在缓冲池中.如果在,则直接插入,如果不再,则先放入一个插入缓冲区中.然后再以一定的频率执行插入缓冲和非聚集索引页子节点的合并操作.使用条件:非聚集索引,非唯一,原因如下:

  • primary key 是按照递增的顺序进行插入的,异常插入聚族索引一般也顺序的,非随机IO。
  • 写唯一索引要检查记录是不是存在,所以在修改唯一索引之前,必须把修改的记录相关的索引页读出来才知道是不是唯一、这样Insert buffer就没意义了,要读出来(随机IO),所以只对非唯一索引有效。

1.3. insert buffer的原理
对于为非唯一索引,辅助索引的修改操作并非实时更新索引的叶子页,而是把若干对同一页面的更新缓存起来做,合并为一次性更新操 作,减少IO,转随机IO为顺序IO,这样可以避免随机IO带来性能损耗,提高数据库的写性能,具体流程:
1) 先判断要更新的这一页在不在缓冲池中

a、若在,则直接插入;
b、若不在,则将index page 存入Insert Buffer,按照Master Thread的调度规则来合并非唯一索引和索引页中的叶子结点

2) Master Thread的调度规则 
a、主动merger: innodb主线程定期完成,用户线程无感知 
主动merge通过innodb主线程(svr_master_thread)判断:若过去1s之内发生的I/O小于系统I/O能力的5%,则主动进行一次insert buffer的merge操作。merge的页面数为系统I/O能力的5%,读取采用async io模式。每10s,必定触发一次insert buffer meger操作。meger的页面数仍旧为系统 I/O能力的5%。

  • 主线程发出async io请求,async读取需要被merge的索引页面
  • I/O handler 线程,在接受到完成的async I/O之后,进行merge

b 、被动merge: 用户线程完成,用户能感受到meger操作带来的性能影响

  • insert操作,导致页面空间不足,需要分裂(split)。由于insert buffer只针对单个页面,不能buffer page split[页已经在内存里],因此引起页面的被动meger。同理,update操作导致页面空间不 足;purge导致页面为空等。总之,若当前操作引起页面split or merge,那么就会导致被动merge;
  • insert操作,由于其它各种原因,insert buffer优化返回false,需要真正读取page时,要进行被动merge。与一不同的是,页在disk上,需要读取到内存里;
  • 在进行insert buffer操作,发现insert buffer太大,需要压缩insert buffer,这时需要强制被动merge,不允许 insert 操作进行。

2 两次写

Insert Buffer带给InnoDB存储引擎的是性能上的提升,doublewrite(两次写)带给InnoDB存储引擎的是数据页的可靠性。
当发生数据库宕机时,可能InnoDB存储引擎正在写入某个页到表中,而这个页只写了一部分,比如16KB的页,只写了前4KB,之后就发生了宕机,这种情况被称为部分写失效(partial page write)。在InnoDB存储引擎未使用doublewrite技术前,曾经出现过因为部分写失效而导致数据丢失的情况。


有经验的DBA也许会想,如果发生写失效,可以通过重做日志进行恢复。这是一个办法。但是必须清楚地认识到,重做日志中记录的是对页的物理操作,如偏移量800,写‘aaaa’记录。如果这个页本身已经发生了损坏,再对其进行重做是没有意义的。这就是说,在应用重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是doublewrite。在InnoDB存储引擎中doublewrite的体系架构如图所示:

innodb_doublewrite.png

3 自适应哈希索引

哈希(hash)是一种非常快的查找方法,在一般情况下这种查找的时间复杂度为O(1),即一般仅需要一次查找就能定位数据。 而B+树的查找次数,取决于B+树的高度,在生产环境中,B+树的高度一般为3~4层,所以需要3~4次的查询。

InnoDB存储引擎会监控对表上各索引页的查询。如果观察到建立哈希索引可以带来速度提升,则建立哈希索引,称之为自适应哈希索引(Adaptive Hash Index, AHI)。AHI是通过缓冲池的B+树页构造而来,因此建立的速度很快,而且不需要对整张表构建哈希索引。InnoDB存储引擎会自动根据访问的频率和模式来自动地为某些热点页建立哈希索引。

AHI有一个要求,对这个页的连续访问模式必须是一样的。例如对于(a,b)这样的联合索引页,其访问模式可以是下面情况:

  • where a=xxx
  • where a =xxx and b=xxx 
    访问模式一样是指查询的条件是一样的,若交替进行上述两种查询,那么InnoDB存储引擎不会对该页构造AHI。

AHI还有下面几个要求:

  • 以该模式访问了100次
  • 页通过该模式访问了N次,其中N=页中记录*1/16

InnoDB存储引擎官方文档显示,启用AHI后,读取和写入速度可以提高2倍,辅助索引的连接操作性能可以提高5倍。AHI的设计思想是数据库自优化,不需要DBA对数据库进行手动调整。

4 异步IO

  • sync IO :同步IO 即每进行一次IO操作,此次操作结束才能继续接下来的操作。 但是如果用户发需要等待出一条索引扫描的查询,那么这条SQL查询语句可能需要扫描多个索引页,也就是需要进行多次的IO操作。在每扫描一个页并等待期完成再进行下一次的扫描是没有必要的。
  • 异步IO: 用户可以在发出一个IO请求后立即再发出另一个IO请求,当全部IO请求发送完毕后,等待所有IO操作的完成,这就是AIO。

AIO另一个优势可以将多个IO,合并为1个IO,以提高IO效率。例如:用户需要访问3页内容,但这3页时连续的。同步IO需要进行3次IO,而AIO只需要一次 就可以了。

5 刷新领接页

当刷新一个脏页时,innodb会检测该页所在区(extent)的所有页,如果是脏页,那么一起进行刷新。这样做,通过AIO将多个IO写入操作合并为一个IO操作。在传统机械磁盘下有着显著优势

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值