MySQL之InnoDB浅析

news2025/7/18 0:35:57

InnoDB是一个兼顾高可靠性和高性能的通用存储引擎。在 MySQL 5.7 中,InnoDB是默认的 MySQL 存储引擎。

InnoDB 的主要优势

  • 支持事物,具备crash-safe的能力
  • 支持行锁以及MVCC,具备良好的多用户并发性和性能
  • Buffer Pool,提升热点数据的查询效率以及数据频繁更新时的效率
  • 聚簇索引,基于主键的查询有更小的IO次数,更加高效
  • 支持外键

架构图

在这里插入图片描述

Buffer Pool

Buffer Pool用于在 InnoDB访问时缓存表和索引数据,并且对于热点数据的访问有很好的加速效果。

Buffer Poold在内存中以链表的形式存在,该链表基于变种LRU进行管理。当新的数据页被添加到Buffer Pool时,会被添加到这个链表靠近中间的位置,这个位置被称为“midpoint”。这种插入策略将链表分成了两个子链表:

  • 靠近头部的一端是最近经常访问的热点数据(new区)
  • 靠近尾部的一端是最近较少访问的冷数据(old区)

在这里插入图片描述

当数据页被添加到old区后,如果该数据页又被再次访问了,并且其被添加到old区的时间超过一个阈值(默认是一秒,由innodb_old_blocks_time控制),则该数据页会被挪到new区的头部,其他数据向尾部移动。

随着数据页的不断读入以及链表中数据页访问频率的变化,new区跟old区中的某些数据页会不断的向尾部移动,直到最终被移除。

Change Buffer

Change Buffer用于缓存二级非唯一索引页的更新操作,加速insert、update、delete这类语句的执行效率。

相对于聚集索引,二级索引的插入顺序相相对随机,此时需要将数据页读入内存来判断插入位置,这个过程会产生很多随机IO。

对于二级索引中的非唯一索引,索引页的更新肯定不会引发唯一约束的冲突。此时便可以直接将更新操作保存在内存中,等到真正需要用到这些更新影响到的索引页时,再将这些更新应用到被影响的索引页即可。这种方式可以避免大量的随机IO访问,并且,读取之前更新的次数越多,收益越高。

可以通过[innodb_change_buffering](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_change_buffering)改变执行策略

  • all

    默认值:缓冲插入、删除和purge。

  • none

    不要缓冲任何操作。

  • inserts

    缓冲插入操作。

  • deletes

    缓冲删除操作。

  • changes

    缓冲插入和删除操作。

  • purges

    缓冲在后台发生的物理删除操作。

通过[innodb_change_buffer_max_size](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_change_buffer_max_size) 指定Change Buffer在Buffer Pool中的占比。默认25%,最大50%。

Redo Log

Redo Log用于实现事物的持久性(Durability),它让MySQL拥有了崩溃恢复能力。

Redo Log通过追加的方式进行数据写入,且记录的是数据的变化(表空间号、数据页号、磁盘文件偏移 量、更新值)。这样有两个好处,第一是顺序IO,第二是减少了刷到磁盘的数据量(16KB可以记录许多个数据页的改动)。这也是为什么不直接用数据文件或者Doublewrite Buffer来实现持久性的原因。

Redo Log由以两部分组成:

  1. Log files(默认100MB,最大128GB):磁盘上的文件,大小固定。通过checkpoint技术实现循环写入。

  2. Log Buffer(默认为 16 MB):内存区域,用于保存事物运行中需要被被写入到redo log的数据。这些数据默认会在事物提交时从内存刷入磁盘,当然,如果事物过大,Log Buffer不足以完全缓存这些数据,则会提前刷盘。

    同时,可以通过指定innodb_flush_log_at_trx_commit来控制Log Buffer里的数据如何写入和刷新到磁盘。有如下三个选项:

    • 1 :每次提交事务时刷盘
    • 0:默认每秒刷盘一次,可通过[innodb_flush_log_at_timeout](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_flush_log_at_timeout)指定间隔。未刷盘事务可能会在crash中丢失
    • 2:事物提交后先写到os cache,并每秒刷盘。未刷盘事务可能会在crash中丢失

    Log Buffer通过对Redo log的批量刷盘(不同事物同时提交时会一起刷),避免了频繁的磁盘IO。

两阶段提交

由于BinLog处于Server层,Redo Log处于存储引擎层。为了保证Redo Log跟BinLog的一致性,在InnoDB写完Redo Log后会先通知执行器RedoLog已写入(prepare)。然后执行器会对BinLog执行写入操作。等到BinLog写入成功,执行器通知InnoDB,事物进入commit。

Doublewrite Buffer

在刷脏页时,数据页首先会被写到Doublewrite Buffer,然后才会被写到Innodb的数据文件。

在MySQL里,页大小默认为16KB,而OS页大小通常默认时4KB。这意味着**MySQL将Buffer Pool中一页数据刷入磁盘,要写4个OS页。而这并不是一个原子操作。**如果突然断电,就有可能存在只刷了2个OS页的情况。此时,数据页里部分数据(LSN)已经丢失,像这种情况,是无法靠Redo Log恢复的。

而Doublewrite Buffer里有完整的页信息,所以此时可以从Doublewrite进行恢复。那么,如果在写Doublewrite Buffer的时候断电呢?那就再重启后重新读入数据页并应用Redo Log再重新写DoubleWrite Buffer即可。

Undo Log

Undo Log用于实现事物的原子性(atomicity)以及MVCC。

Undo Log由rollback segments组成,单个表空间默认/最大128个。segmentUndo Slots组成,slot的数量取决于页大小。页大小为16kb时单个segment下slot的数量为1024。slot里存放的是用于回滚的具体信息。

segment为Innodb的事物并发提供支持。segment的数量与能够支持的事物并发数正相关,通常一个slot能够支持一个事物。具体计算方式也很简单,参考事物并发数计算。

通过[innodb_rollback_segments](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_rollback_segments)指定segment数量

MVCC

MVCC全称Multiversion concurrency control,及多版本并发控制。是数据库管理系统
常用的一种并发控制,也用于程序设计语言实现事务内存。

MVCC目的是为了解决读写锁造成的多个、长时间的读操作阻塞写操作的问题。在特定的隔离级别下,事务读操作读到的数据项是一个历史快照,写操作不覆盖已有数据项,而是创建一个新的版本,直至所在操作提交时才变为可见。这种方式使得事务在整个运行过程中看到的都是它启动时的数据状态。

InnoDB 里面每个事务有一个唯一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请,按申请顺序严格递增。

在事物更新数据时,会将transaction id以及更新前的数据保存在undo log中。同时,会将transaction id保存在被修改的行的隐藏列DB_TRX_ID中。行记录中还有一个隐藏列,叫DB_ROLL_PTR,存储的事一个指向rollback segment的指针。如果在该事物未提交时有其他事物来读取该行,就会通过这个指针来回溯并重建未修改前的数据。回溯的程度通过比较读事物跟redo log中的transaction id来决定,读事物能看到的数据必须是在其启动时已经提交的事物作出的数据修改

参考

https://dev.mysql.com/doc/refman/8.0/en

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

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

相关文章

Redis过期键及内存淘汰策略

写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一、Redis数据库的组织方式 Redis服务器将所有的数据库 都保存在src/server.h/redisServer结构中的db数组中。db数组的每个entry都是src/server.h/redisDb结构,每个redisDb结构代表一个数据库。Redis默认有16个…

测试用例设计方法之正交法

概念: 正交试验设计是研究多因素多水平的一种设计方法,它是根据正交性,由试验因素的全部水平组合中挑选出部分有代表性的点进行试验,通过对这部分试验结果的分析了解全面试验的情况,找出最优的水平组合。正交试验设计…

49 - 多态的概念和意义

---- 整理自狄泰软件唐佐林老师课程 1. 函数重写回顾 父类中被重写的函数依然会继承给子类子类中重写的函数将覆盖父类中的函数通过作用域分辨符(::)可以访问父类中的函数 p->print()不符合预期,期望调用子类中的print,实际调…

【知识网络分析】研究者合作网络(co-investigator)

研究者合作网络(co-investigator) 1 数据集读取2 网络数据集精简3 网络最大子群获取并可视化4 社团群体分类筛选5 求解网络图中节点中心度相关的指标值并进行可视化1 数据集读取 此处的合作作者(co-investigator)是指基金数据中的作者,数据集 来自于官网提供的加拿大国家…

redis数据库windows下c语言库的编译

使用cmake和make工具进行windows下的编译 下载 1.hiredis下载地址 https://github.com/redis/hiredis 克隆源码 2.cmake下载地址 https://cmake.org/ 3.make for windows http://www.equation.com/servlet/equation.cmd?fa=make 4.mingw 64位 https://download.csdn.net/d…

USB Network Native Driver for ESXi更新支持ESXi8.0

在ESXi8.0发布一个多月后,社区版的USB网卡驱动终于在flings上更新了,USB Network Native Driver for ESXi | VMware Flings Nov 23, 2022 - v1.11 Added support for ESXi 8.0 ESXi800-VMKUSB-NIC-FLING-61054763-component-20826251.zip md…

如何根据不同需求给Word文档设置保护?

Word文档可以设置不同的保护模式,我们可以根据不同需求选择合适的方法,下面介绍一下常用的3种方法。 方法一: 如果不想Word文档被随意打开,我们可以设置打开密码,只有输入正确的密码才能打开文件。 首先&#xff0c…

Metabase学习教程:视图-4

将数据可视化为直方图 学习何时使用直方图,以及元数据库如何使创建直方图更容易。 我们将逐步创建直方图,它是一种条形图,显示连续范围内的数据组。柱状图有助于深入了解人们可能购买的商品的数量、他们可能购买的价格范围,甚至…

JS 数据结构:集合

集合 集合是由一组无序且唯一(即不能重复)的项组成的。该数据结构使用了与有限集合相同的数学概念。ES6 JS 原生实现了集合 Set 数据结构(具体看这篇文章JS Set 与 weakSet),但是没有取两集合交集、并集、差集的 API …

机器学习笔记之高斯网络(二)高斯贝叶斯网络

机器学习笔记之高斯网络——高斯贝叶斯网络引言回顾高斯网络贝叶斯网络:因子分解高斯贝叶斯网络:因子分解引言 上一节介绍了高斯网络及其条件独立性,本节将介绍高斯贝叶斯网络。 回顾 高斯网络 高斯网络最核心的特点是:随机变…

SpringBoot 多点互斥登录(web应用安全) 保姆级教程

1.什么是互斥登录 在实际生活中,很多网站都做了多点登录互斥的操作,简单来说就是同一个账号,只能在一台电脑上登录,如果有人在其他地方登录,那么原来登录的地方就会自动下线,再进行操作就会弹出登录界面。 …

【远程调用 MySQL数据库并操作】——使用NATAPP搭建内网穿透远程访问MySQL数据库并使用 Python新建、写入、读取、删除数据【详细版】

所有的程序都是免费的!! Python MySQL NATAPP 点个赞留个关注吧!! NATAPP 安装使用教程 官网 NATAPP 下载 官网 NATAPP配置教程 1、进入NATAPP 登录/注册 进行登录,没有的注册一下,需要实名认证哦&am…

python基础之字符串

文章目录一、字符串定义二、字符串相关使用三、空白字符表示哪些?四、实例1.要求:顺序并且居中对齐输出以下内容2.要求:1.将字符串中的空白字符全部删去;2.再使用“ ”作为分隔符,拼接成一个整齐的字符串五、字符串的切…

【vscode】远程云主机的报错

win11 之前在另一台电脑上的vscode是可以的 新电脑拷贝了vs的配置,但是远程不行了。 Install terminal quit with output: 过程试图写入的管道不存在。 发现连接不到远程以为是konw hosts 的问题, 删除了要访问ip的内容,还是不行&#x…

网络程序设计——异步选择模型(基于消息的选择、基于事件的选择)

目录 一、异步选择模型 1、基于消息的选择模型 (1)WSAAsyncSelect模型 (2) WSAAsyncSelect()函数 (3)使用 WSAAsyncSelect模型接收数据的过程 (4)WSAAsyncSelect模型的编程方法…

IDEA常用插件

笔记来源于B站视频 以下为视频的地址 【【尚硅谷】IDEA2022全新版教程,兼容JDK17(快速上手Java开发利器)】https://www.bilibili.com/video/BV1CK411d7aA?p26&vd_source581d732b20cb23e01428068f153a99ed 推荐1:Alibaba J…

MCE丨重组蛋白常见的融合标签

Q:什么是融合标签? A:融合标签是指利用 DNA 体外重组技术,在目的蛋白 N 端或 C 端进行融合表达的特定蛋白、多肽或寡肽标签。 Q:融合标签有什么作用? A:重组蛋白通过融合标签与包被在固相基质上…

第六章《类的高级特性》第5节:接口

在Java语言中,一个类只能继承一个父类,专业上把这种继承机制称为“单继承”。单继承是一种较为稳妥继承机制,能够规避很多潜在的问题,但这种继承机制的局限性也显而易见:子类不能从多个父类中继承属性和方法,从而无法最大程度的减少重复劳动。为了弥补这个缺陷,Java语言…

web前端-javascript-关系运算符(>、>=、<、<=、非数值,Unicode 编码说明)

文章目录关系运算符1. 说明2. > 大于号3. > 大于等于4. < 小于号5. < 小于等于6. 非数值的情况6.1. 对于非数值进行比较时&#xff0c;会将其转换为数字然后再比较6.2. 如果符号两端都是字符串时&#xff0c;不会将其转换为字符串进行比较6.3. 任何值和 NaN 做任何…

为什么单线程的Redis如此的快(Why is single-threaded Redis so fast)

视频地址&#xff1a;YouTube Why is Redis so fast? What fundamental design decisions did the developers make more than a decade ago that stood to test of time. Let’s take a look. Redis is a very popular in-memory database. It’s rock solid, easy to use, a…