Mysql之Innodb存储引擎

1.Innodb数据存储

innodb如今能够做到mysql的默认数据存储引擎,肯定有着其好处的,那么innodb有什么好处呢?

1. 当意外断电或者重启, InnoDB 能够做到奔溃恢复,撤销没有提交的数据
2.InnoDB 存储引擎维护自己的缓冲池,在访问数据时将表和索引数据缓存到主存中。经常使用的数据直接从内存中处理。这种缓存适用于许多类型的信息,并加快了处理速度。在专用数据库服务器上,高达80% 的物理内存通常分配给缓冲池
3.where groupby orderBy 的自动优化、基于索引。
4. 插入、更新和删除是通过一种称为更改缓冲的自动机制进行优化的

 innodb存储引擎是作为数据存储的,那么肯定是要落盘的,那么落盘落到哪里?innodb又是如何管理这些数据的呢?

在Innodb中会有一个表空间的概念,又可以分为很多的类型,比如系统表空间、通用表空间、独立表空间等,我们的数据可以有选择的决定存入到哪个表空间中,关于表空间的具体介绍可以参考官网,这里不再介绍,MySQL :: MySQL 8.0 Reference Manual :: 17.6.3 Tablespaces

那么表空间又是如何管理的呢? 每个表空间都是由大小相同的page页来组成的,默认page页是16kb,也可以根据innodb_page_size来设定页的大小

在表空间中从上到下会依次划分为segment(段)、extent(区)、page(页)、rows(行)

segment: 段是表空间的分区,一个表空间中,会有多个段组成,常见的短有数据段、索引段、8.0之前有回滚段

extent: 区来管理页,当页的大小在16K以下,一个区的大小是1M,如果32K2M,64K则为4M。后面磁盘释放分配都是以区为单位. 所以,一个extent下最少可以存储64page

page:对于4KB8KB16KB32KBinnodb_page_size设置,最大行长度略小于数据库页面大小的一半。例如,对于默认的16KB InnoDB页面大小,最大行长度略小于8KB。对于64KBinnodb_page_size设置,最大行长度略小于16KB

rows:表的行格式决定了其行的物理存储方式,这反过来又会影响查询和 DML 操作的性能,为什么影响 我们在讲索引的时候会讲到

 行存储如果超过,那么该页就只存储指针,其它内容交由外部溢出页来存储

行存储分为四种存储格式,不同的行格式,存储方式、空间性能都不一样

REDUNDANT:  冗余行格式,主要是旧版本 mysql 的兼容,数据和行索引信息分开存储,某些查询操作会快,但是需要额外的空间,所以是之前老版本的格式设计
COMPACT:  减少了存储行间,官网说大约 20% ,但是增加了cpu 的负荷。导致一些查询的性能问题
DYNAMIC:  动态行格式 该行格式允许长度可变,所以会根据情况来决定是否需要更多空间,5.7 后的默认行格式
COMPRESSED:  压缩行格式 COMPACT 进行了压缩,减
少了存储空间使用,比如 text 长文本 会进行压缩,但是检索的时候,必须
进行解压,牺牲了 cpu

mysql默认的行格式是dynamic

也可以在创建表的时候定义表的行格式

CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;

 2.Innodb内存加载及管理

我们已经知道,我们的数据最终是会落盘到磁盘中的,那么假如我们每次检索都去磁盘获取,明显性能会比较慢。所以Innodb为了性能的优化,采用了内存缓存机制,在内存中缓存相应的数据。这个内存区间叫做BufferPool.

缓冲池是主内存中的一个区域,在innodb访问时缓存表和索引数据。缓冲池允许直接从内存访问频繁使用的数据,从而加快处理速度

SELECT @@innodb_buffer_pool_size; -- 默认134217728字节/1024/1024   128M

也可以设置bufferpool的大小

mysql> SET GLOBAL innodb_buffer_pool_size=402653184;

既然有了这个内存缓冲区,那么这个内存与磁盘数据是怎么交互的呢?

2.1内存与磁盘数据交互机制

该交互机制采用的是页加载机制,这是为什么呢?

1. 如果用行交互,那么假如我查询 200 条数据,那么 200 条数据都不在我们内存的话,需要跟磁盘交互200 次,但是 page 可能只有 1.2 page
2. 也不会用 extent 区来交互,因为一个 extent 包含 64 个页。可能我只需要查一条数据,但是会加载64 个页到内存,导致内存浪费。

处于内存的利用率与性能考虑,Innodb选择了page页

那么整体流程是什么样子的呢?

1. 假如一条查询语句 查询出的数据有 2.3.4.5.6.7 6 条数据
2. bufferpool 中查看 2.3.4.5.6.7 所在的 page 页是否存在
3. 如果存在,直接返回
4. 如果不存在,根据 2.3.4.5.6.7 的数据所在的 page 页,去磁盘加载,加载完后保存到内存
5. 下次查询 id=5, 由于在内存中已经存在,直接返回

 另外,mysql还提供了一种预读机制,我们每次读取数据的时候,会将对应的page页加载到内存,预读机制就是,我就算没读到,也能提前把一些可能读到的数据加载到内存。

预读机制: MySQL :: MySQL 8.0 Reference Manual :: 17.8.3.4 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead)

 预读请求是一种i/o请求,用于在缓冲池中异步预取多个页面,在请求某些页面时,预计即将需要extent的其它页面。那么这个预计的页面是怎么知道的呢?主要通过两种预读算法

线性预读:按照访问顺序的页来执行预加载 某个区里面的页面有多少个页按顺序访问了,那么就会预加载这个区里面所有的页。具体多少个页被顺序访问,具体配置为innodb_read_ahead_threshold

随机预读:根据缓存池中已有的页来预加载,如果在缓冲池中找到了来自同一个区连续的13个页面,InnoDB会异步发出一个请求来预取该区剩余的页面。开关控制:innodb_random_read_ahead

 2.2BufferPool内存管理

假如我们查询到的页或者与加载的页都加载到我们的bufferpool,那么肯定要进行管理,因为我们的bufferpool内存也是有限的,不能无休无止的往里面添加。此时,就可以采用淘汰策略。(还记得redis中的淘汰策略吗)

历史总是惊人的相似,Mysql也是采用LRU算法去进行page页淘汰的,只不过实现方式稍有变化。

        默认的LRU 算法,是最近没有访问的优先去淘汰,所以一般我们实现就是用链表保存,新的数据添加到链表头部,然后淘汰从链表尾部进行淘汰。
        这个一般是没有问题的,但是在InnoDB 里面,就这样不行,为什么不行,因为在InnoDB 里面有个预读的概念。何为预读,就是用户在访问某些页的时候,关联的一些页我也可能会给你读出来保存到bufferPool ,但是用户可能根本就不用。
         InnoDB 有预读机制,只是猜测会用,但是不一定真的会用到,那么假如如 果用传统的 LRU 实现,那么我们会发现,会预加载很多页到 bufferpool ,但 是可能用户根本不适用,但是又淘汰不了,既占用了内存,也没有得到很 大的性能提升!

 针对Innodb的特殊情况,采用LRU的变种

将LRU列表分为2段,链表的前面8分之5是新页列表,后面的8分之3是老页,然后淘汰页面从后面尾部进行淘汰。具体流程如下:

1. 当新的页面缓存到 BufferPool ,先加入到 oldSublist 的头部,包括预读的页。
2. old 的页面被访问时 , 会添加到 new 的头部成为一个最近访问的页
3.new sublist 的链表会随着新数据的加入向后移动 同样的 old 的链表会随着新数据的加入向后移动;淘汰old sublist 的链尾。

分析: 既然不确定用到,那么就先放到一个中间位置,当用到了后再放到头部避免淘汰。如果加载了但没用到,随着推移,慢慢的进行淘汰掉,从而来提升内存的利用率。 

3.数据同步机制

从第2节中我们可以知道我们的数据都会以page页的方式同步到我们的内存,那么在我们的系统中,就有2份数据,一份在内存,一份在磁盘,那么这2个数据是怎么去做数据同步的呢?怎么保证数据的一致性?

为什么不直接同步到磁盘呢?一致性问题不久解决了。假如说每次操作都需要先跟磁盘同步,那么就会出现以下问题:

1. 由于内存跟磁盘交互的最小单位是 page 页,那么你改动一行数据,整个页都需要跟磁盘进行交互同步。
2. 这个更改的数据你是不知道在哪个磁盘位置的,属于一个随机 IO

上面的这两个问题 都会导致每次操作数据会非常慢。

所以innodb采用的是异步刷盘机制, 何为异步刷盘,就是我优先去更改内存的数据,然后通过异步线程去进行跟磁盘的同步。这个时候,肯定会出现内存跟磁盘不一样的页,这种页就叫做脏页。

出现脏页怎么办?innodb是如何才能够保证数据的一致性呢?

Mysql提供了一个doubleWrite机制,简单点,就是备份。

什么是双写呢?就是当page页刷新到磁盘的时候,把这个page数据写到不同的地方去,当出现问题时,由备份来达到持久性跟数据的一致性。

双写过程:

1. 当脏页被写入到缓存池(也称为内存池)时,它们将被写入到Doublewrite缓冲区中,而不是直接写入到磁盘上的表空间中
2.  Doublewrite 缓冲区是一个位于内存中的缓冲区,用于存储即将写入磁 盘的脏页的数据。在写入到 Doublewrite 缓冲区后,数据将被写入到两 个不同的磁盘区域,这样即使其中一个磁盘出现问题,数据也可以从另 一个磁盘恢复。在写入到磁盘之前,数据会被缓存到磁盘的 Write
Cache 中,确保数据能够快速写入磁盘。
3. 在数据被写入磁盘之前, Doublewrite 缓冲区中的每个脏页的 LSN (日志序列号)都会被更新,以确保数据的一致性。这是因为LSN 是一种用于恢复数据的唯一标识符,它可以确保在数据库出现故障时,数据可以恢复到一个一致的状态。
4. 一旦数据被成功写入到磁盘上的两个不同区域并且 LSN 已经被更新,数据就被标记为干净页并从缓存池中移除。此时,这个脏页的数据已经被持久化到磁盘中,并且数据库可以确保数据的一致性和可靠性。

分析:DoubleWrite机制会占用一部分内存和磁盘的空间,同时也会导致一定的性能损失,但这是为了保证数据的安全性和可靠性而进行的权衡。

3.1 change-buffer 

现在我们知道了,我们更改的数据都是异步同步到磁盘的,但是在更改之前呢,我们内存中不存在的数据,是不是还得从磁盘拿取,那可不可以再优化一下,我先改了放到内存,然后下次读取到相关数据再进行合并呢。

innodb中也有这样的优化,叫做change-buffer(更改缓冲区)

更改缓冲区是一种特殊的数据结构, 当这些页面不在缓冲池中时,它会缓 存对二级索引 页面的更改, 稍后会在其他读取操作将页面加载到缓冲池中时合并。
为啥是二级索引,因为二级索引的插入跟修改一般是无序的,所以 IO 开销
更大,更需要提升性能。
还有主键索引。唯一的,所以我们要去磁盘进行唯一校验,本来就需要去
磁盘进行 IO ,如果内存没有数据的话。

4.RedoLog

我们已经知道了innodb中的数据是异步刷新到磁盘的,那么假如,在刷新到磁盘之前就宕机了。那么数据是不是就丢失了,innodb怎么数据的一致性与持久性呢?

innodb引入了一个redolog。也叫做重做日志,当发生异常的时候,导致数据丢失的时候,从redolog日志中找到想要的数据。

因为 InnoDB 的数据操作是只会实时去操作我们的 bufferpool page 页的,然后通过其他的一些异步方式将bufferpool 中的数据同步到磁盘,所以,数据丢失是很容易产生的。那么就需要我们的RedoLog 来保证数据的不丢失。它属于InnoDB 存储引擎层面实现

4.1 RedoLog格式

当操作数据时,就会记录一条redolog日志,这个日志只是一条记录,记录的是在什么表空间,什么页对数据惊醒了什么样的更改。

 

type: 操作类型 插入、修改还是删除'
spaceId: 表空间 ID
page num : 锁在的页
data: 修改的前后数据

这种记录在某个偏移量发生了什么变更的这种日志格式,也叫做物理日志。

4.2 redolog的存储与写入

innodb通过rdolog解决数据丢失的问题。所以redolog肯定是一个基于磁盘的数据结构,肯定会写入磁盘,每次sql语句提交的时候,都会去写入redolog

首先,要保证数据不丢失,那么肯定是要落到磁盘的。那么肯定会有redolog的磁盘文件。

思考: 既然都要写入磁盘,为什么不直接将数据同步到表空间的磁盘呢?

1. 因为 bufferPool 跟磁盘交互的最小单位是 page ,所以,只要 page 里面改 动一条数据,整个page 都会进行跟磁盘同步,导致不必要的同步。 RedoLog只会同步某些记录。
2. 你改动的数据是随机的,不是顺序的,随机 IO 的性能比较慢,但是RedoLog是一直往上加,是顺序 IO ,速度比数据 page 同步要快。

另外,redolog为了保证数据的一致性跟持久性的同时,性能得到保证,减少磁盘IO,于是作者又开辟了一个logBuffer的内存区间,缓存redolog,redolog不马上写到磁盘,而是先写到logbuffer,然后一次性的从logbuffer同步到磁盘。

4.3 logbuffer 跟磁盘的同步

只要触发了刷新到磁盘,就能百分比保证数据不丢失吗?如果不丢失,性能是不是又会有所损耗

所以作者提供了不同的方案供选择:

SELECT @@innodb_flush_log_at_trx_commit; //RedoLog同步方案默认设置为1
1 : 每次事务提交时,将日志刷新到磁盘,安全性高,能够保证持久性,默认配置
0 : 每秒从内存写到操作系统,并且刷新( fsync() )到硬盘,可能会导致数据丢失
2 :每次写入 logbuffer 并且写到操作系统,但是每秒 fsync() 到磁盘,最终刷新交给操作系统操作,只要操作系统不挂,也能保证持久性,但是操作系统挂了,数据没刷新就会数据丢失

 

当然,除了配置 innodb_flush_log_at_trx_commit的 同步机制外,还有以下情况也会导致redolog同步到磁盘

a.buffer空间不足时

b. 后台异步线程定期刷新

c.正常关闭服务器

d.checkPoint检查哪些数据没有同步到磁盘的时候

4.4 redolog的开启与禁用

SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled'; -- 查看RedoLog是否开启
ALTER INSTANCE disable INNODB REDO_LOG -- 禁用RedoLog

5.总结

        innodb作为一个存储数据的引擎;利用了表空间,分段分区分页的思想对数据进行管控;并且采用了内存缓冲池的机制减少IO,提升数据交互的效率;但是就可能造成两处数据的不一致,形成脏页,innodb就又采用了双写机制,提前做好备份,能够应该故障和灾难时,数据的不一致性问题。但是这解决了更改的性能,更改之前还需要从磁盘中拿,于是innodb又提出了change-buffer(更改缓冲区),改了先放内存,下次用了再同步。当然,这些都是采用了异步刷盘的思想,如果,刷盘之前就宕机了呢?innodb又提出了一个很重要的概念,redolog,每一次变更,都会存储到该磁盘中,相较于存储到表空间的磁盘中,该磁盘是顺序添加的,顺序IO性能肯定比随机IO要好。说白了,innodb就是采用了各种内存缓存机制,来减少与磁盘的IO次数,从而提高性能的。有了缓存,那么就肯定少不了内存管理机制数据的一致性和持久性

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

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

相关文章

医院挂号就诊系统的设计与实现

前端使用Vue.js 后端使用SpiringBoot MyBatis 数据使用MySQL 需要项目和论文加企鹅:2583550535 医院挂号就诊系统的设计与实现_哔哩哔哩_bilibili 随着社会的发展,医疗资源分布不均,患者就诊难、排队时间长等问题日益突出,传统的…

Hadoop3:HDFS的Fsimage和Edits文件介绍

一、概念 Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目 录和文件inode的序列化信息。 Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先 会被记录到Ed…

二叉树的链式结构

1.二叉树的遍历 2.二叉树链式结构的实现 3.解决单值二叉树题 1.二叉树的遍历 1.1前序,中序以及后序遍历 二叉树的遍历是按照某种特定的规则,依次对二叉树的结点进行相应的操作,并且每个结点只操作一次。 二叉树的遍历有这些规则&#xff…

主流电商平台商品实时数据采集API接口||抖音电商数据分析实例|可视化

— 1 — 抖音电商数据【抖音电商API数据采集】分析场景 1. 这里,我们选择“伊利”这个品牌作为案例进行分析,在短短的4个月里,从最初每月营收17.07万,到6月份达到了2485.54 万,伊利的牛奶,有点牛&#xff…

Spring 对 Junit4,Junit5 的支持上的运用

1. Spring 对 Junit4,Junit5 的支持上的运用 文章目录 1. Spring 对 Junit4,Junit5 的支持上的运用每博一文案2. Spring对Junit4 的支持3. Spring对Junit5的支持4. 总结:5. 最后: 每博一文案 关于理想主义,在知乎上看到一句话:“…

Xline社区会议Call Up|在 CURP 算法中实现联合共识的安全性

为了更全面地向大家介绍Xline的进展,同时促进Xline社区的发展,我们将于2024年5月31日北京时间11:00 p.m.召开Xline社区会议。 欢迎您届时登陆zoom观看直播,或点击“阅读原文”链接加入会议: 会议号: 832 1086 6737 密码: 41125…

通过cmd命令行使用用3dmax自带的vray渲染

有时调试需要使用vray渲染vrscene文件看效果,只装有3dmax下可以使用自带vray渲染,在3dmax的渲染日志里面看自带引擎路径 使用命令行进入到此目录 执行命令指定vr文件即可看到效果,如:vray.exe -sceneFile“C:\test15\202405241…

Cesium与Three相机同步(2)

之前实现了将Three相机同步到Cesium相机Cesium与Three相机同步(1)-CSDN博客 现在是将Cesium相机同步到Three相机,从而实现了相机双向同步。 <!DOCTYPE html> <html lang="en"><head><title>three.js webgl - orbit controls</title&g…

【教学类-58-03】黑白三角拼图03(4*4宫格)总数算不出+随机抽取10张

背景需求&#xff1a; 【教学类-58-01】黑白三角拼图01&#xff08;2*2宫格&#xff09;256种-CSDN博客文章浏览阅读318次&#xff0c;点赞10次&#xff0c;收藏12次。【教学类-58-01】黑白三角拼图01&#xff08;2*2宫格&#xff09;256种https://blog.csdn.net/reasonsummer/…

【Jmeter】使用Jmeter进行接口测试、跨线程组获取参数

Jmeter接口测试 Jmeter设置成中文实操练习-跨线程组提取参数&#xff0c;使用值HTTP请求默认值&HTTP信息头管理器 相信打算从事测试工程师的同学们&#xff0c;肯定对Jmeter是耳熟能详的。使用Jmeter可以进行接口测试、性能测试、压力测试等等&#xff1b;这个章节介绍如何…

cocos 通过 electron 打包成 exe 文件,实现通信问题

cocos 通过 electron 打包成 exe 文件&#xff0c;实现通信问题 首先&#xff0c;我使用的 cocos 版本是 2.4.12&#xff0c;遇到一个问题&#xff0c;是啥子呢&#xff0c;就是我要把用 cocos 开发出来的项目打包成一个 exe 可执行程序&#xff0c;使用的是 electron &#xf…

【C++算法】BFS解决多源最短路问题相关经典算法题

1.01矩阵 既然本章是BFS解决多源最短路问题&#xff0c;也就是说有若干个起点&#xff0c;那我们就可以暴力一点&#xff0c;直接把多源最短路径问题转化成若干个单源最短路径问题&#xff0c;然后将每次的步数比较一下&#xff0c;取到最短的就是最短路径的结果&#xff0c;这…

arcgis 10.6 工具栏操作error 001143 后台服务器抛出异常

arcgis 10.6 工具栏操作error 001143 后台服务器抛出异常 环境 win10arcgis 10.6 问题 执行定义投影要素转线出现 Error: 001143:后台服务器抛出异常&#xff08;差点重装10.6&#xff09; 如下图所示&#xff1a; 解决方法 通过在菜单工具条上单击地理处理 > 地理处…

设计模式使用(成本扣除)

前言 名词解释 基础名词 订单金额&#xff1a;用户下单时支付的金额&#xff0c;这个最好理解 产品分成&#xff1a;也就是跟其他人合做以后我方能分到的金额&#xff0c;举个例子&#xff0c;比如用户订单金额是 100 块&#xff0c;我方的分成是 80%&#xff0c;那么也就是…

OceanMind海睿思通过上海数交所数商认证,提供高质量数据治理和数据咨询服务

近日&#xff0c;中新赛克海睿思成功通过上海数据交易所的数商认证&#xff0c;获得上海数据交易所颁发的“数据产品开发服务商”、“数据治理服务商”和“数据咨询服务商”三大证书。 作为由深圳市创新投资集团有限公司投资控股的高新技术企业&#xff0c;国家级专精特新“小巨…

如何通过OpenHarmony的音频模块实现录音变速功能?

简介 OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;是由开放原子开源基金会孵化及运营的开源项目&#xff0c;是面向全场景、全连接、全智能时代的智能物联网操作系统。 多媒体子系统是OpenHarmony系统中的核心子系统&#xff0c;为系统提供了相机、…

Java入门基础学习笔记43——包

什么是包&#xff1f; 包是用来分门别类的管理各种不同程序的&#xff0c;类似文件夹&#xff0c;建包有利于程序的管理和维护。 建包的语法规则&#xff1a; package cn.ensource.javabean;public class Car() {} 在自己的程序中调用其他包下的程序的注意事项&#xff1a; 1…

动手学深度学习——层和块

1. 层 层是一个将输入数据转换为输出数据的神经网络组件。每个层都会对输入数据进行一定的操作&#xff0c;例如线性变换、非线性激活函数等&#xff0c;以产生输出数据。 torch.nn模块提供了各种预定义的层&#xff0c;如线性层、卷积层、池化层等&#xff0c; nn.Linear&a…

BLE学习笔记(0.0) —— 基础概念(0)

前言 &#xff08;1&#xff09;本章节主要是对BLE技术进行简单的介绍&#xff0c;熟悉蓝牙技术的发展过程&#xff0c;了解相关术语方便后续的学习。 &#xff08;2&#xff09;为了防止单篇博客太长以至于看不下去&#xff0c;因此我基础概念章节分为两篇来写。 &#xff08;…

Mysql教程(0):学习框架

1、Mysql简介 MySQL 是一个开放源代码的、免费的关系型数据库管理系统。在 Web 开发领域&#xff0c;MySQL 是最流行、使用最广泛的关系数据库。MySql 分为社区版和商业版&#xff0c;社区版完全免费&#xff0c;并且几乎能满足全部的使用场景。由于 MySQL 是开源的&#xff0…