MySQL InnoDB关键特性总结

写缓冲(Change Buffer)

  1. 目的:提升插入性能;
  2. 使用插入缓冲的条件:
    • 非聚集索引;
    • 非唯一索引;
    • 就是说必须是辅助索引且非唯一索引;
    • 为何?insert buffer的设计是为了避免读取索引页,如果是唯一索引,在插入时需要判断插入的记录是否唯一,这需要读取辅助索引页,导致失去insert buffer的设计意义;
  3. 插入缓冲:change buffer是对insert buffer的加强,insert buffer只对insert有效,change buffer对insert、delete、update(delete+insert)、purge都有效;
  4. change buffer作为buffer pool的一部分,innodb_change_buffering参数的值有:
    • all:默认值,缓存insert、delete、purge操作;
    • inserts:缓存insert操作;
    • deletes:缓存delete操作;
    • changes:缓存insert、delete操作;
    • purges:缓存后台执行的物理删除操作;
    • none:不缓存;
  5. innodb_change_buffer_max_size参数:控制使用的大小,默认25%,最大可设置50%,如果mysql实例中有大量的修改操作,可考虑增大该参数;
  6. insert buffer的数据结构是一颗B+树;
    • 全局只有一颗insert buffer B+树,负责对所有表的辅助索引进行insert buffer;
    • 这颗B+树放在共享表空间中,试图通过独立表空间ibd文件恢复表中数据时,往往会导致check table失败,因为表中的辅助索引中的数据可能还在insert buffer中,也就是共享表空间中,所以ibd文件恢复后,还需要repair table操作来重建表上所有的辅助索引;
  7. 对满足插入缓存条件的插入,每一次的插入不是写到索引页中;
    • 会先判断插入的非聚集索引页是否在缓冲池中,如果在直接插入;
    • 如果不在,则先放到insert buffer中,再按照一定的频率进行合并操作,再写会磁盘;
    • 通常可以将多个插入合并到一个操作中,目的是为了减少随机IO带来的性能损耗;
  8. 一定频率进行合并操作,这个频率有什么条件?
    • 辅助索引页被读取到缓冲池中,正常的select先检查insert buffer是否有该非聚集索引页存在,有则合并插入;
    • 辅助索引页没有可用空间。空间小于1/32页大小,会强制合并操作;
    • master thread每秒和每10秒的合并操作;

两次写(double write)

  1. doublewrite缓存位于系统表空间的存储区域,用来缓存innodb的数据页从innodb buffer pool中flush之后并写入到数据文件之前;
  2. 当操作系统或数据库进程在数据页写入磁盘的过程中崩溃,可以在doublewrite缓存中找到数据页的备份,用来执行crash恢复;
  3. 数据页写入到doublewrite缓存的动作所需要的io消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入;
    在这里插入图片描述
    根据上图知道:
  4. 内存中doublewrite buffer大小2M;物理磁盘上共享表空间中连续的128个页,也就是2个区(extent)大小同样为2M;
  5. 对缓冲池脏页进行刷新时,不是直接写磁盘。
    • 第一步:通过memcpy()函数将脏页先复制到内存中的doublewrite buffer;
    • 第二步:通过doublewrite分两次,每次1M顺序的写入共享表空间的物理磁盘上。这个过程中,doublewrite页是连续的,因此这个过程是顺序的,所以开销并不大;
    • 第三步:完成doublewrite页的写入后,再将doublewrite buffer中的页写入各个表空间文件中,此时写入是离散的,可能会较慢;
    • 如果操作系统在第三步的过程中发生了崩溃,在恢复过程中,可以从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件中,再应用重做日志;

自适应哈希索引

  1. Innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,此索引成为热数据,建立hash索引以提升查询速度,此建立是自动建立哈希索引,故称为自适应哈希索引(adaptive hash index);
  2. 自适应哈希索引会占用innodb buffer pool;
  3. 只适合搜索等值(=)的查询,对于范围查找等操作,是不能使用的;

异步IO

为了提高磁盘操作性能,当前的数据库系统都采用异步IO的方式来处理磁盘操作。

异步IO:用户可以在发出一个IO请求后立即再发出另外一个IO请求,当全部IO请求发送完毕后,等待所有IO操作完成,这就是AIO。与AIO对应的是Sync IO,即每进行一次IO操作,需要等待此次操作结束才能继续接下来的操作。

异步IO的好处:

1、不用等待直接响应上一个用户的请求;

2、多次的请求在一起排序,请求的数据页是在一起的,一次读出来,减少多次读。(数据库的读写请求队列放在文件系统中单独分配的一块小内存结构里,非文件系统的缓存)

刷新邻接页

当刷新一个脏页时,innodb存储引擎会检测该页所在区(extent)的所有页,如果是脏页,那么一起进行刷新。这样做的好处显而易见,通过AIO可以将多个IO写入操作合并为一个IO操作,增大写入量,减少了物理写IO,故该工作机制在传统机械磁盘下有着显著的优势。

  • 在写入次数基本不增加的情况下,增加了写入的量;
  • 加速了脏页的回收;
  • 充分利用double write每次1M写入的特征;
  • 这个功能打开以后会发现iostat里面的wrqm(合并写)这个值会比较高;

1、是不是可能将不怎么脏的页进行了写入,而该页之后又会很快变成脏页?

2、固态硬盘有着较高的 IOPS,是否还需要这个特性?

为此,InnoDB 存储引擎从 1.2.x 版本开始提供了参数 innodb_flush_neighbors,用来控制是否启用该特性。对于传统机械硬盘建议启用该特性,而对于有着超高 IOPS 性能的固态硬盘,则建议将该参数设置为 0、即关闭此特性。


版权声明:本文为fangmeng1997原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。