InnoDB中必须要了解的几个关键特性

news2024/12/25 12:17:23

InnoDB引擎在设计中使用了很多技术思想。下面我们主要介绍一些InnoDB的关键特性,帮助你去更好了解 InnoDB。

关键特性

    • 1.预读
      • (1)预读的两种算法
      • (2)在InnoDB中相关配置
    • 2.插入缓冲
      • 2.1 Insert Buffer
      • 2.2 Change Buffer
      • 2.3 Insert Buffer的内部实现
      • Merge Insert Buffer
    • 3.二次写(double write)
    • 4.自适应哈希索引
    • 5.异步IO
    • 6.刷新邻接页

1.预读

预读,我们从字面就可以知道是指:预先读取一些信息。为什么要预读?判断哪些数据可以提前读取到内存中,从而减少IO次数。我们知道硬盘、内存的IO速度差距极大,在内存充裕的条件下,可以极大减少IO时间。但是如果内存不足,预读的数据还没有被真正读取,就被淘汰,那就做了无用功。所以要正确认识预读
认识预读前,先了解 InnoDB数据的逻辑存储单元——表空间、段、区和页。
file
上图可以看到这样的层级关系:表空间 -> 段 -> 区(64个页)-> 页(默认16KB)

(1)预读的两种算法

预读请求是指 预取缓冲池中的多个页面的异步IO请求,以预测这些页面即将出现的需求。请求在一个区段中引入所有页面。InnoDB使用两种预读算法来提高IO性能:

  • 线性预读(Line read-ahead):一种基于 按顺序访问的缓冲池中的页面来预测可能很快需要哪些页面的技术。通过配置参数innodb_read_ahead_threshold,触发异步读请求所需的顺序页访问次数,来控制InnoDB执行预读操作的时间。在此之前,InnoDB只会在读取当前extent的最后一页时,计算是否对整个下一个extent发出异步预取请求。
    例如,如果将该值设置为48,则只有在当前区段中有48个页面被连续访问时,InnoDB才会触发线性预读请求。
  • Random read-ahead(随机预读)是一种技术,可以根据缓冲池中已经存在的页面预测何时可能需要页面,而不管这些页面的读取顺序如何。如果在缓冲池中发现同一个区段的13个连续页面,InnoDB会异步发出一个请求来预取该区段的剩余页面。通过配置变量innodb_random_read_ahead来控制随机读的。

(2)在InnoDB中相关配置

对于预读参数有两个参数:

mysql> show variables like '%read_ahead%';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| innodb_random_read_ahead    | OFF   |
| innodb_read_ahead_threshold | 56    |
+-----------------------------+-------+

innodb_random_read_ahead:开启随机预读技术,优化InnoDB I/O。默认关闭
innodb_read_ahead_threshold:控制InnoDB用于将页面预取到缓冲池中的线性预读的灵敏度

2.插入缓冲

2.1 Insert Buffer

先谈谈我们为什么要引入 Insert Buffer ?

在InnoDB引擎中,无论我们是否自定义主键(如果我们不定义唯一索引,引擎会帮我们建立隐藏的主键列)。因为InnoDB引擎必须要使用主键来构建 聚集索引。一般的主键都是自增的,这样在插入时是顺序插入的。并且聚集索引页也是顺序的,不容易造成频繁的页分裂。

但是我们一般不仅仅使用聚集索引,通常我们会设置非聚集索引不唯一的索引。那么在进行插入时,数据还是按主键来进行顺序存放的。但是对于非聚集索引页叶子节点的插入就不是顺序的了。这时就需要离散地访问非聚集索引页。由于随机写,就会导致插入操作性能下降。这是B+树的特性决定了非聚集索引插入的离散性。

提醒:也不是所有非聚集索引都是写都是完全离散或者说无序的。在某些情况下,非聚集索引的插入依然有序或者比较有序。例如:记录创建时间字段作为 索引列时,插入顺序是根据插入时间。此时插入就是 顺序写了

那么我们如何解决非聚集索引插入时的随机写。InnoDB引擎就开创性的设计了Insert Buffer,对于非聚集索引的插入或者更新操作,不是每次直接插入索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,若在,则直接插入。如果不在,则先放入一个 Insert Buffer 对象中,然后告诉 数据库已经将数据插入到叶子结点中(实际并没有)。选择放在 Insert Buffer中暂存,然后再以一定频率和情况进行 Insert Buffer 和 非聚集索引页子节点的 合并操作。这是通常可以使得多个插入 合并称一个操作。因为可能存在不少插入操作,其实操作的是同一个索引页中。这就大大提高了对于非聚集索引的插入性能。

但是并不是所有索引都可以使用 Insert Buffer,需要满足以下条件:

  • 索引是非聚集索引
  • 索引列不是唯一的

当满足以上两个条件时,InnoDB存储引擎会使用 Insert Buffer。第一个条件显而易见,聚集索引不需要使用Insert Buffer。那为什么 索引列值不能限定它是唯一的呢?因为在插入缓冲时,如果需要去查询索引页来判断插入的记录为唯一性。那么就会造成随机读索引页,也就失去设计 Insert Buffer 的必要了。

需要注意到:

  • 当进行大量插入操作(涉及到非聚集索引)后,如果此时数据库发生宕机,这时势必有大量的 Insert Buffer 并没有合并到实际的非聚集索引中去。因此此时进行恢复,可能会需要很长时间。
  • 在写密集的情况下,插入缓冲会占用过多缓存池内存(innodb_buffer_pool),默认最大可以占用到1/2的缓冲池内存。这对于其他的操作可能会产生一些影响。

2.2 Change Buffer

InnoDB从1.0.x版本后开始引入了 Change Buffer,可以看作 Insert Buffer的升级。从此,InnoDB存储引擎可以对 DML操作——INSERT、DELETE、UPDATE都进行缓冲,他们分别是:Insert Buffer、Delete Buffer、Purge Buffer。和之前的Insert Buffer一样,Change Buffer只适用于非唯一的非聚集索引。

2.3 Insert Buffer的内部实现

Insert Buffer 的数据结构是一颗B+树。在MySQL4.1之前,每张表都有一颗 Insert Buffer B+ 树。而现在的版本中,全局只有一颗 Insert Buffer B+树,负责对所有的表的非聚集索引进行 Insert Buffer。这颗树存放在共享表空间中,默认也就是 ibdata1中。因此,试图通过独立表空间ibd文件恢复表中数据时,往往会导致 CHECK TABLE失败。这是因为表的非聚集索引中的数据可能还在 Insert Buffer,也就是共享表空间中,所以通过 ibd 文件进行恢复后,还需要 REPAIR TABLE 操作来重建表上所有的非聚集索引。

Insert Buffer 是一颗B+树,因此其也是由叶子结点和非叶子结点组成。非叶子结点存放的是查询的 search key。
file
search key 占用9个字节,其中 space 表示待插入记录所在表的表空间id,在 InnoDB 存储引擎中,每个表有一个唯一的 space id,可以通过 space id 查询得知时哪张表。space 占用4字节。marker占用1字节,它是用来兼容老版本的 Insert Buffer。offset 表示页所在的偏移量,占用4字节。

当一个非聚集索引要插入到页(space,offset)时,如果这个页不在缓冲池中,那么 InnoDB 存储引擎首先根据上述规则构造一个 search key,接下来查询 Insert Buffer 这颗B+树,然后再将这条记录插入到 Insert Buffer B+树的叶子节点中。
file
对于插入到叶子结点的记录,并不是直接把待插入的记录插入,而是需要根据一定规则构造。结构如上图。
space、marker、offset字段和之前的非叶子节点中的含义一样,一共占用9个字节。第四个字段 metadata 占用4字节,由三部分组成:

  • IBUF_REC_OFFSET_COUNT:
    占用2个字节,用来排序每个记录进入 Insert Buffer 的顺序。因为 InnoDB开始支持 ChangeBuffer,所以这个值同样被引入到 Insert Buffer中。通过这个字段来标记操作顺序,保证通过顺序回放能得到记录的正确值。
  • IBUF_REC_OFFSET_TYPE:操作类型
  • IBUF_REC_OFFSET_FLAGS:标志位,当前只有 IBUF_REC_COMPACT。

从 Insert Buffer 叶子节点的第5列开始,就是实际插入记录的各个字段了。因此较原插入记录,Insert Buffer B+树的叶子节点记录额外需要 9+4 字节的开销。

因为启用 Insert Buffer后,原先插入非聚集索引页中的记录可能会被插入到 Insert Buffer B+树中。所以我们需要保证每次 Merge Insert Buffer页必须成功。由此需要引入 Insert Buffer Bitmap,它是一个特殊的页,用来标记每个非聚集索引页的可用空间。这个页的类型是 Insert Buffer Bitmap。

Insert Buffer Bitmap 中 每个非聚集索引页占用4位(bit):

  • IBUF_BITMAP_FREE:占用2bit,枚举值:0-表示无可用剩余空间;1-表示剩余空间大于1/32页;2-表示剩余空间大于1/16页;3-表示剩余空间大于1/8页;
  • IBUF_BITMAP_BUFFERED:占用1bit,为1时表示该非聚集索引页有记录被缓存在 Insert Buffer B+树中
  • IBUF_BITMAP_IBUF:占用1bit,为1时表示该页为 Insert Buffer B+树的索引页

因此 每个 Insert Buffer Bitmap 页可以用来追踪16384个非聚集索引页,也就是256个区。每个 Insert Buffer Bitmap 页都在16384个页的第二个页中。

Merge Insert Buffer

前面说到的 Insert Buffer、Change Buffer 是一颗B+树。若需要实现插入记录的非聚集索引不在缓冲池中,那么需要将非聚集索引记录首先写到这颗B+树汇总,但是 Insert Buffer 中的记录什么时候 merge 到真正的 非聚集索引中呢?
可以概括,Merge Insert Buffer 的操作一般发生在以下几种时机:

  • 非聚集索引页被读取到缓冲池时
    当执行正常的 SELECT 查询操作时,需要检查 Insert Buffer Bitmap页,然后确认该辅助索引页是否有记录存放于 Insert Buffer B+树中。若有,则将 Insert Buffer B+树中该页的记录插入到该非聚集索引页中。可以看到对该页多次的记录操作通过一次操作合并到了原有的非聚集索引页中,因此性能有大幅提高。

  • Insert Buffer Bitmap 页追踪到该辅助索引页中已无可用空间时
    上面也提到过 Insert Buffer Bitmap 页是用来追踪每个辅助索引页的可用空间。若插入非聚集索引记录时检测到插入记录后可用空间会小于1/32页,则会强制进行一个合并操作。将 Insert Buffer B+树中该页的记录及待插入的记录一起插入到 非聚集索引页中。

  • Master Thread
    在 Master Thread 线程中每秒或每10秒回进行一次 Merge Insert Buffer 的操作,不同之处在于每次进行merge操作的页的数量不同。它是随机地选择 Insert Buffer B+树的一个页,读取该页中的space及之后所需要数量的页。

3.二次写(double write)

Insert Buffer 带给了 InnoDB存储引擎的是性能的提升,二次写带给 InnoDB 的是数据页的可靠性

InnoDB中页的默认是16KB,而Linux中页的大小是4KB。所以当数据库宕机时,如果InnoDB正在写入某个页到表中,那么这个页可能只写了一部分。这种情况叫做 部分写失效。这种失效,不能通过重做日志解决。因为重做日志中记录的是对原有页的物理操作,它是基于原来的页的,如果页数据已经损坏,重做也是无意义的。

所以我们需要一个副本,当发生写入失效的时候,通过页的副本来还原该页,再进行重做。这就是 double write。

double write 有两部分组成,一部分是处于内存中的 double write buffer,大小为2MB,另外一个部分是处于物理磁盘上共享表空间中连续的2个区(128个页),大小也为2MB。对缓冲池中的脏页进行刷新,并不是直接写磁盘,而是会通过memcpy函数将脏页数据先复制到内存中的 double write buffer中,之后通过 double write buffer 分两次,每次1MB顺序地写入到 共享空间的物理磁盘上,然后马上调用 fsync函数,同步到磁盘。

因为写入到 磁盘中的doulewrite页是连续的,所以这个过程是顺序写,速度很快。在完成 double write 页的写入后,再从 内存中 double write buffer中将脏页写入到 各脏页所在的表空间文件中。因为脏页之间不是连续的,是各个表空间的脏页,所以此时写是离散写,速度很慢。

通过参数 skip_innodb_doublewrite 可以禁止使用 二次写功能,提升较快速度,但是可能会发生写失效问题。

有些文件系统本身提供了部分写失效的防范机制,如ZFS文件系统。那么此时则没有必要开启 二次写 功能。

4.自适应哈希索引

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

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

AHI 是有要求的,只有页的连续访问模式是一样的,才会对该页构建AHI。例如:对联合索引页(a,b),其访问模式可以是:

  • where a = xxx
  • where a = xxx and b = yyy
    访问模式一样指的是查询的条件一样,若交替的执行上述另种查询,那么InnoDB不会对该页进行构建。除此之外还有如下要求:
  • 以该模式访问了至少100次
  • 页通过该模式访问了至少N次,其中N=页中记录* 1/16

官方文档中说过,启动AHI后,读取和写入速度可以提高2倍,辅助索引的连接操作性能可以提高5倍。AHI是很好的数据库自优化的模式。我们可以自己通过命令 SHOW ENGINE INNODB STATUS可以看到当前AHI的使用状况。

注意:哈希索引只适用于等值查询

5.异步IO

为了提高磁盘操作性能,目前数据库系统都采用异步IO(AIO)的方式来处理磁盘操作。InnoDB存储引擎也是如此。与AIO对应的是Sync IO,即每进行一次IO操作。需要等待此次操作结束后,才能继续接下来的操作。但是如果用户发出的是一条索引扫描的查询,那么这条SQL查询语句可能需要扫描多个索引页,也就是进行多次IO操作。在每扫完一个页并等待其完成后再进行下一次的扫描,这是没有必要的。用户可以在发出一个IO请求后 立即再发出其他IO请求,当全部IO请求发送完毕后,等待所有IO操作的完成,这就是AIO。

AIO的另外一个优势就是可以进行 IO Merge操作,也就是将多个IO合并成1个IO,这样可以提高 IOPS 的性能。例如用户需要访问页的(space,page_no)为:(8,6)、(8,7)、(8,8)。每个页的大小为16KB,那么同步IO需要进行3次IO操作。而AIO会判断到这三个页是连续的。因此AIO底层只会发送一个IO请求,从(8,6)开始读取48KB的页。

InnoDB1.1.x之前,AIO的实现是通过InnoDB存储引擎中的代码来模拟实现的。而从InnoDB1.1.x开始,提供了内核级别的AIO支持,称为Native AIO。

通过参数 innodb_use_native_aio控制是否启用 Native AIO,在Linux操作系统下,默认为ON。官方测试,启用 Native IO,速度可以提升75%。

InnoDB中,read ahead 方式的读取是由AIO完成,脏页的写入等磁盘写入操作也是由AIO完成。

6.刷新邻接页

InnoDB 存储引擎提供 刷新邻接页(Flush Neighbor Page)的特性。其工作原理为:当刷新一个脏页时,InnoDB存储引擎会检测该页所在区(extent)的所有页,如果是脏页,那么一起进行刷新。这样做的好处就是,通过AIO可以将多个IO写入操作合并成一个IO操作,该工作机制在传统机械硬盘下有显著的优势。但是机制会引出下面2个问题:

  • 是否会把不怎么脏的页 进行了写入,而该页之后又很快变成脏页?
  • 固态硬盘有很高的 IOPS,那么是否还需要这个机制?

使用参数 innodb_flush_neighbors控制是否开启

对于机械硬盘建议使用该特性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/455996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨域的五种最常见解决方案

这是一篇笔记 什么是跨域? 跨域不是问题,是一种安全机制。浏览器有一种策略名为同源策略,同源策略规定了部分请求不能被浏览器所接受。 值得一提的是:同源策略导致的跨域是浏览器单方面拒绝响应数据,服务器端是处理…

C#基于asp.net的企业人事管理系统的研究与实现

(一)任务 1.本课题的任务是对人事管理系统的管理过程进行分析,列出逻辑实现过程,对系统进行逻辑设计和数据库设计; 2.主要实现系统管理、档案管理、考勤管理、薪水管理等功能; 3.实现企业员工的相关信息&am…

一篇文章教你解决node-sass 4.12.0 安装失败,一劳永逸

已知: 使用mac电脑使用的node版本是v14.20.0 问题:在安装node-sass 4.12.0的时候报错如下 看到这一堆错误,千万不要立马复制粘贴到浏览器去搜,感觉像无头苍蝇乱撞,好歹稍微看一下什么意思。 显而易见是有一个文档40…

浅析低代码开发的典型应用构建场景v

在数字经济蓬勃发展的大势之下,企业软件开发人员供给不足、开发速度慢、开发成本高、数字化和智能化成效不明显等问题日益凸出,阻碍了企业的数字化转型。 而近年来,低代码的出现推动了经济社会的全面提效,也成为人才供求矛盾的润…

【Docker】限制已运行容器的Cpu和内存

docker限制已运行容器的Cpu和内存 本文首发于 慕雪的寒舍 1.问题描述 最近云服务器的内存经常不够用,而且是莫名其妙的增多,在腾讯云的控制台里面看,4g的内存占用了3.2g,就卡到连ssh都连不上了 PS: 已换过网络和设备&#xff0c…

只要10分钟,零代码基础搞定炫酷大屏设计(内附详细教程)

近几年可视化大屏再次被推上热搜,无论是已经结束的疫情时代指挥中心大屏,还是每年购物节的大屏数据成交额,或者是日常会议中的大屏分析,到处都是可视化大屏的身影。 有人会说,这种大屏一定需要大量的财力、技术顶端的…

开源构建系统Buck2发布

看来最近 Meta 的工程师是一点都没有闲着,前两天刚开源 AI 图像分割模型,这不就又发布了名为 Buck2 的开源构建系统。 Buck2 是一个已经在 Meta 内部使用了一段时间的大型构建系统,目前 Meta 有数千名开发人员正在使用该构建系统,…

IP地址配置

1.vi /etc/sysconfig/network-scripts/ifcfg-ens33 (在配置文件中修改) 配置文件内容为: IPADDR:配置IP地址 NETMASK:配置子网掩码 GATEWAY:配置网关 DNS:配置dns地址 BOOTPROTO:设置获取ip的方式\DHCP为动态获取\ static为…

C++(GCC)生成和使用静态库

C(GCC)生成和使用静态库 文章目录 C(GCC)生成和使用静态库1、前言1.1 什么是静态库1.2 静态库优缺点1.3 C使用静态库的方法1.4 注意事项 2、linux下C生成静态库.a3、链接使用静态库 更多精彩内容👉个人内容分类汇总 &a…

可算是熬出头了,测试4年,费时8个月,入职阿里,涨薪14K

前言 你的努力,终将成就无可替代的自己。 本科毕业后就一直从事测试的工作,和多数人一样,最开始从事点点点的工作,看着自己的同学一步一步往上走,自己还是在原地踏步,说实话这不是自己想要的状态。 一年半…

蓝牙耳机接打电话哪个比较好?接打电话最好的蓝牙耳机

技术已经发展到如此程度,耳机可以淹没嘈杂环境中不断出现的杂音,同时还能让我们在通话、音乐和娱乐方面保持清晰,既然如此,我们就来整理一下2023年适合通话和娱乐的无线耳机清单。 一、南卡小音舱Lite2蓝牙耳机 参考价格&#x…

Ubuntu系统下Python的虚拟环境搭建方法

文章目录 参考链接:一、Python虚拟环境的作用及创建方法简介1. 创建虚拟环境的必要性2. venv、virtualenv、pipenv三种创建虚拟环境方法比较2.1 搭建Python虚拟环境的方法2.2 venv、virtualenv方法2.3 pipenv方法 二、 virtualenv搭建虚拟环境1. 环境准备1.1 安装vi…

AI数字人产品“世优BOTA”发布会落幕,世优科技纪智辉演讲回顾

4月20日,世优科技式发布了新一代AI数字人产品——“世优BOTA”。在会上,世优科技创始人纪智辉介绍了数字人技术、驱动形式、数字人应用、“世优BOTA”的前世今生及未来。 以下是纪智辉的演讲内容概要: 各位嘉宾、各位朋友:大家下…

Storm proxies动态SEO监测优化为什么要大量用到http代理ip?

SEO监测和优化通常需要大量使用HTTP代理IP来实现以下几个方面的需求: 模拟不同地区的搜索结果:搜索引擎通常会根据用户所在地区提供不同的搜索结果,因此需要使用HTTP代理IP模拟不同地区的搜索结果,以便监测和优化针对不同地区的SE…

Matlab 相机标定

详细的原理可以看这篇 计算机视觉-相机标定,写的很赞 Step1. 准备 首先准备打印好的黑白棋盘格图片,并且保证表面的平整,例如35*35的棋盘格,贴在亚克力板上。 Step2. 拍摄 用相机拍摄棋盘格分别在取景框左上角、右上角、左下…

openGauss数据库pg_xlog爆满问题解决

文章目录 问题现象问题定位解决办法总结 问题现象 最近有一个之前搭的环境登不上了,好久没用想拿来测试的时候发现启动不了。启动时报错: [Errno 28] No space left on device query也不行了,提示没有空间了。 查询磁盘使用情况 df -h …

车间设备能源管理系统作用有哪些?

由于能源消耗不断的增加,对于高耗能企业要实现节能转型,淘汰落后高耗能产业,提供能源的有效利用,实现节能减排,合理利用能源,从而促进企业的经营绩效。 车间设备能源管理系统优点 1.精细化管理 可以对车…

探索【Stable-Diffusion WEBUI】的附加功能:图片缩放抠图

文章目录 (零)前言(一)附加功能(图片处理)(1.1)处理对象(Source)(1.2)缩放(Scale)(1.2.1&#xff…

【论文精读】TNNLS 2022 - 基于深度学习的事件抽取研究综述

【论文精读】TNNLS 2022 - 基于深度学习的事件抽取研究综述 【论文原文】:A Survey on Deep Learning Event Extraction Approaches and Applications 【作者信息】:Li, Qian and Li, Jianxin and Sheng, Jiawei and Cui, Shiyao and Wu, Jia and Hei,…

畅谈自然语言处理——初识NLP技术

畅谈自然语言处理——初识NLP 文章目录 畅谈自然语言处理——初识NLP一、引言二、NLP技术的定义分类三、三个发展阶段1、基于规则的算法2、基于统计的NLP算法3、基于深度学习的NLP算法 结语 一、引言 最近,一个名为ChatGPT的模型将计算机领域震撼,它以对…