当前位置: 首页 > news >正文

MySQL(进阶篇--InnoDB引擎)

文章目录

  • InnoDB
  • 一、逻辑存储结构
  • 二、架构
    • 总结构
    • 2.1 内存结构
    • 2.2 磁盘结构
    • 2.3 后台线程
    • 总结
  • 三、事务原理
    • 3.1 redo log
    • 3.2 undo log
  • 四、MVCC
  • 五、总结

InnoDB

一、逻辑存储结构

在这里插入图片描述
在这里插入图片描述

二、架构

总结构

MySQL5.5 版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。
下面是InnoDB架构图,侧为内存结构侧为磁盘结构

在这里插入图片描述

2.1 内存结构

在这里插入图片描述
在左侧的内存结构中,主要分为这么四大块儿: Buffer Pool、Change Buffer、Adaptive
Hash Index、Log Buffer。

1). Buffer Pool
InnoDB存储引擎基于磁盘文件存储,访问物理硬盘和在内存中进行访问,速度相差很大,为了尽可能
弥补这两者之间的I/O效率的差值,就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行磁
盘I/O。 在InnoDB的缓冲池中不仅缓存了索引页和数据页,还包含了undo页、插入缓存、自适应哈希索引以及
InnoDB的锁信息等等。

缓冲池 Buffer Pool,是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增
删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频
率刷新到磁盘,从而减少磁盘IO,加快处理速度。

缓冲池以Page页为单位,底层采用链表数据结构管理Page。
根据状态,将Page分为三种类型:
• free page:空闲page,未被使用。
• clean page:被使用page,数据没有被修改过。
• dirty page:脏页,被使用page,数据被修改过,也中数据与磁盘的数据产生了不一致。
在专用服务器上,通常将多达80%的物理内存分配给缓冲池 。参数设置: show variables
like ‘innodb_buffer_pool_size’;
在这里插入图片描述

2). Change Buffer

Change Buffer,更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据Page
没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer
中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。

Change Buffer的意义是什么呢?

在这里插入图片描述
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新
可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了
ChangeBuffer之后,我们可以在缓冲池中进行合并处理,减少磁盘IO。

在这里插入图片描述

3). Adaptive Hash Index

自适应hash索引,用于优化对Buffer Pool数据的查询。MySQL的innoDB引擎中虽然没有直接支持
hash索引,但是给我们提供了一个功能就是这个自适应hash索引。因为前面我们讲到过,hash索引在
进行等值匹配时,一般性能是要高于B+树的,因为hash索引一般只需要一次IO即可,而B+树,可能需
要几次匹配,所以hash索引的效率要高,但是hash索引又不适合做范围查询、模糊匹配等。

InnoDB存储引擎会监控对表上各索引页的查询,如果观察到在特定的条件下hash索引可以提升速度,
则建立hash索引,称之为自适应hash索引。

自适应哈希索引,无需人工干预,是系统根据情况自动完成。
参数: adaptive_hash_index

4). Log Buffer

Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log 、undo log),
默认大小为 16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事
务,增加日志缓冲区的大小可以节省磁盘 I/O。

参数:
innodb_log_buffer_size:缓冲区大小
innodb_flush_log_at_trx_commit:日志刷新到磁盘时机,取值主要包含以下三个:
1: 日志在每次事务提交时写入并刷新到磁盘,默认值。
0: 每秒将日志写入并刷新到磁盘一次。
2: 日志在每次事务提交后写入,并每秒刷新到磁盘一次。

在这里插入图片描述

2.2 磁盘结构

在这里插入图片描述
①:System Tablespace:系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据。(MySQL5.x版 本中还包含InnoDB数据字典、undolog等)
参数: innodb_ data_ file_ path

②:File-Per-Table Tablespaces:每个表的文件表空间包含单个InnoDB表的数据索引,并存储在文件系统.上的单个数据文件中。
参数: innodb_ file_ per_ table

默认是开启的;开启就意味着每张独立的表都有一个表空间,并不会再①中存放;

ibd文件每一个文件都是一个表空间文件,其中存放的就是这张表的表结构及表中的数据和索引;

③:General Tablespaces:通用表空间,需要自己通过CREATE TABLESPACE语法创建用表空间,在创建表时,可以指定该表空间。(了解)

创建:
在这里插入图片描述

create tablespace a_stu(随意别名) add datafile 'student.ibd' engine = innodb;

使用:

create table a(id int primary key auto increment,name varchar (10)) engine = innodb tablespacets a_stu;

④:Undo Tablespaces:撤销表空间,MySQL 实例在初始化时会自动创建两个默的undo表空间(初始大小16M),用于存储undo log日志。

⑤:Temporary Tablespaces:临时表空间。 InnoDB 使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。

⑥:Doublewrite Buffer Files:双写缓冲区,innoDB引擎将数据页从Buffer Pool新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

在这里插入图片描述
⑦:RedoLog:重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log) ,前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用。

以循环方式写入重做日志文件,涉及两个文件:在这里插入图片描述

**redo log:**它是循环写的,不会永久保存,每隔一段时间,清理之前没有用的redo log;因为redo log,当事务提前,也就没什么用了,因为它的作用是保证异常时,
继续数据恢复,从而保证事务的持久性;

2.3 后台线程

在这里插入图片描述
数据如何从内存写入磁盘的,就是这中间部分:后台线程

在这里插入图片描述
在这里插入图片描述

总结

整个体系结构就是:当我门业务操作的时候,那么会直接操作左边内存的缓冲区,如果缓冲区当中没有数据,会将右边磁盘当中的数据加载回来,然后再存储在缓存区当中;我门在增删改查的时候,都会去操作左边的缓冲区,然后缓冲区当中的数据会以一定的频率或者说一定的时机,要通过这组后台线程刷新到磁盘当中,然后再磁盘当中进行永久化保存(永久保存主要指的是我门表当中的数据和索引等相关信息,undo log和read log会被回收释放,不会永久保留);

三、事务原理

在这里插入图片描述
底层:
在这里插入图片描述

3.1 redo log

在这里插入图片描述
无redo log情况:
在这里插入图片描述

首先,客户端在进行事务操作时会发起请求去操作MySql服务器,在MySQL的InnoDB引擎中,分为内存结构和磁盘结构,磁盘结构里存放了很多ibd文件,内存结构中有一个很大的缓冲池,缓冲池中缓冲了我们很多数据页的信息。当客户端发起事务操作,在这次事务操作中,包含了多条update和delete语句,那么此时是怎么进行执行的呢?
首先,去操作缓冲区,在缓冲区中查找有没有对应操作的数据,如果没有,此次会通过后台线程把我们数据从磁盘中读取出来,然后缓存在缓冲区中;接下来就可以直接在缓冲区中执行客户发送的事务操作;此时,缓冲区中的数据就会发生变更,而磁盘中的数据没有变更,那么缓冲区中这个变更的数据页就叫脏页,会在一定时机,通过后台线程将其刷新至磁盘中,这个时候内存中的缓冲区和磁盘中数据就一致了。
但是脏页的数据并不是实时刷新的,而是一段时间或者一段频率刷新的,假如,脏页的数据往磁盘中刷新出错了,那么内存中的数据就没刷新到磁盘中。那么,事务都已经提交了并通知了用户成功,但最终在脏页刷新的时候失败了,那么持久性就没得到保障!

有redo log情况:
在这里插入图片描述

脏页数据从内存刷新到磁盘出现错误时,恢复用的,保证持久性。
为什么每次提交时要把redo log刷新到磁盘中?
提交事务时,不先将脏页直接刷新,先把redo log文件异步刷新到磁盘当中,由于是
log日志文件,日志文件都是追加的,此时就是顺序磁盘IO,效率远高于随机磁盘IO。
这种机制就是WAL(先写日志),日志是循环写,不会永久保留,这就是redo log。

3.2 undo log

在这里插入图片描述

四、MVCC

在这里插入图片描述

五、总结

在这里插入图片描述

相关文章:

  • 【Linux修炼】开篇
  • 【数学建模】层次分析(MatlabPython代码实现)
  • 如何用人工智能自动玩游戏
  • PIE-engine 教程 ——影像集合的使用for循环函数(北京市NDVI计算)
  • 数据结构-栈和队列(1)
  • 【微服务】springboot 整合 dubbo3.0
  • c++迭代器STL中的vector简单概述
  • 不可重复读和幻读详解(必看!!!)
  • 2022eclipse下载安装与使用教程
  • 【云原生】zookeeper + kafka on k8s 环境部署
  • 【牛客刷题日记】— Javascript 通关秘籍
  • 深度学习项目部署遇到的错误【记录】
  • 解决无法获取到B站点赞数和播放量的解决办法
  • 【历史上的今天】9 月 19 日:世界上第一个表情符号;微软发布 Virtual PC;苹果 UI 扁平化的开始
  • lio-sam框架:后端里程计、回环、gps融合
  • 【译】JS基础算法脚本:字符串结尾
  • 30天自制操作系统-2
  • Angular 4.x 动态创建组件
  • Iterator 和 for...of 循环
  • Mithril.js 入门介绍
  • React16时代,该用什么姿势写 React ?
  • react-native 安卓真机环境搭建
  • Redis中的lru算法实现
  • Redux系列x:源码分析
  • uni-app项目数字滚动
  • 大型网站性能监测、分析与优化常见问题QA
  • 机器学习中为什么要做归一化normalization
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 网络应用优化——时延与带宽
  • 我建了一个叫Hello World的项目
  • 我这样减少了26.5M Java内存!
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 正则学习笔记
  • 自制字幕遮挡器
  • 【干货分享】dos命令大全
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • $GOPATH/go.mod exists but should not goland
  • (10)STL算法之搜索(二) 二分查找
  • (arch)linux 转换文件编码格式
  • (Ruby)Ubuntu12.04安装Rails环境
  • (SERIES10)DM逻辑备份还原
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • ***监测系统的构建(chkrootkit )
  • ***利用Ms05002溢出找“肉鸡
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)