谈谈MySQL的InnoDB存储引擎

news2024/9/28 19:14:35

大家好,我是易安!

今天我们谈一谈MySQL中InnoDB存储引擎。InnoDB存储引擎作为我们最常用到的存储引擎之一,充分熟悉它的的实现和运行原理,有助于我们更好地创建和维护数据库表。

InnoDB体系架构

InnoDB主要包括了内存池、后台线程以及存储文件。内存池又是由多个内存块组成的,主要包括缓存磁盘数据、redo log缓冲等;后台线程则包括了Master Thread、IO Thread以及Purge Thread等;由InnoDB存储引擎实现的表的存储结构文件一般包括表结构文件(.frm)、共享表空间文件(ibdata1)、独占表空间文件(ibd)以及日志文件(redo文件等)等。

alt

1. 内存池

我们知道,如果客户端从数据库中读取数据是直接从磁盘读取的话,无疑会带来一定的性能瓶颈,缓冲池的作用就是提高整个数据库的读写性能。

客户端读取数据时,如果数据存在于缓冲池中,客户端就会直接读取缓冲池中的数据,否则再去磁盘中读取;对于数据库中的修改数据,首先是修改在缓冲池中的数据,然后再通过Master Thread线程刷新到磁盘上。

理论上来说,缓冲池的内存越大越好。缓冲池中不仅缓存索引页和数据页,还包括了undo页,插入缓存、自适应哈希索引以及InnoDB的锁信息等等。

InnoDB允许多个缓冲池实例,从而减少数据库内部资源的竞争,增强数据库的并发处理能力。

InnoDB存储引擎会先将重做日志信息放入到缓冲区中,然后再刷新到重做日志文件中。

2. 后台线程

Master Thread 主要负责将缓冲池中的数据异步刷新到磁盘中,除此之外还包括插入缓存、undo页的回收等,IO Thread是负责读写IO的线程,而Purge Thread主要用于回收事务已经提交了的undo log,Pager Cleaner Thread是新引入的一个用于协助Master Thread刷新脏页到磁盘的线程,它可以减轻Master Thread的工作压力,减少阻塞。

3. 存储文件

在MySQL中建立一张表都会生成一个.frm文件,该文件是用来保存每个表的元数据信息的,主要包含表结构定义。

在InnoDB中,存储数据都是按表空间进行存放的,默认为共享表空间,存储的文件即为共享表空间文件(ibdata1)。若设置了参数innodb_file_per_table为1,则会将存储的数据、索引等信息单独存储在一个独占表空间,因此也会产生一个独占表空间文件(ibd)。如果你对共享表空间和独占表空间的理解还不够透彻,接下来我会详解。

而日志文件则主要是重做日志文件,主要记录事务产生的重做日志,保证事务的一致性。

InnoDB逻辑存储结构

InnoDB逻辑存储结构分为表空间(Tablespace)、段(Segment)、区(Extent)、页Page)以及行(row)。

alt

1. 表空间(Tablespace)

InnoDB提供了两种表空间存储数据的方式,一种是共享表空间,一种是独占表空间。 InnoDB 默认会将其所有的表数据存储在一个共享表空间中,即ibdata1。

我们可以通过设置innodb_file_per_table参数为1(1代表独占方式)开启独占表空间模式。开启之后,每个表都有自己独立的表空间物理文件,所有的数据以及索引都会存储在该文件中,这样方便备份以及恢复数据。

2. 段(Segment)

表空间是由各个段组成的,段一般分为数据段、索引段和回滚段等。我们知道,InnoDB默认是基于B +树实现的数据存储。

这里的索引段则是指的B +树的非叶子节点,而数据段则是B +树的叶子节点。而回滚段则指的是回滚数据,MVCC就是利用了回滚段实现了多版本查询数据。

3. 区(Extent) / 页(Page)

区是表空间的单元结构,每个区的大小为1MB。而页是组成区的最小单元,页也是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区。

4. 行(Row)

InnoDB存储引擎是面向行的(row-oriented),也就是说数据是按行进行存放的,每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-200行,即7992行记录。

InnoDB事务之redo log工作原理

InnoDB是一个事务性的存储引擎,而InnoDB的事务实现是基于事务日志redo log和undo log实现的。redo log是重做日志,提供再写入操作,实现事务的持久性;undo log是回滚日志,提供回滚操作,保证事务的一致性。

redo log又包括了内存中的日志缓冲(redo log buffer)以及保存在磁盘的重做日志文件(redo log file),前者存储在内存中,容易丢失,后者持久化在磁盘中,不会丢失。

InnoDB的更新操作采用的是Write Ahead Log策略,即先写日志,再写入磁盘。当一条记录更新时,InnoDB会先把记录写入到redo log buffer中,并更新内存数据。我们可以通过参数innodb_flush_log_at_trx_commit自定义commit时,如何将redo log buffer中的日志刷新到redo log file中。

在这里,我们需要注意的是InnoDB的redo log的大小是固定的,分别有多个日志文件采用循环方式组成一个循环闭环,当写到结尾时,会回到开头循环写日志。我们可以通过参数innodb_log_files_in_group和innodb_log_file_size配置日志文件数量和每个日志文件的大小。

Buffer Pool中更新的数据未刷新到磁盘中,该内存页我们称之为脏页。最终脏页的数据会刷新到磁盘中,将磁盘中的数据覆盖,这个过程与redo log不一定有关系。

只有当redo log日志满了的情况下,才会主动触发脏页刷新到磁盘,而脏页不仅只有redo log日志满了的情况才会刷新到磁盘,以下几种情况同样会触发脏页的刷新:

  • 系统内存不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,需要先将脏页同步到磁盘;
  • MySQL认为空闲的时间,这种情况没有性能问题;
  • MySQL正常关闭之前,会把所有的脏页刷入到磁盘,这种情况也没有性能问题。

在生产环境中,如果我们开启了慢SQL监控,你会发现偶尔会出现一些用时稍长的SQL。这是因为脏页在刷新到磁盘时可能会给数据库带来性能开销,导致数据库操作抖动。

alt

LRU淘汰策略

刚刚我们了解了InnoDB的更新和插入操作的具体实现原理,接下来我们再来了解下读的实现和优化方式。

InnoDB存储引擎是基于集合索引实现的数据存储,也就是除了索引列以及主键是存储在B +树之外,其它列数据也存储在B + 树的叶子节点中。而这里的索引页和数据页都会缓存在缓冲池中,在查询数据时,只要在缓冲池中存在该数据,InnoDB就不用每次都去磁盘中读取页,从而提高数据库的查询性能。

虽然缓冲池是一个很大的内存区域,但由于存放了各种类型的数据,加上存储数据量之大,缓冲池无法将所有的数据都存储在其中。因此,缓冲池需要通过LRU算法将最近且经常查询的数据缓存在其中,而不常查询的数据就淘汰出去。

InnoDB对LRU做了一些优化,我们熟悉的LRU算法通常是将最近查询的数据放到LRU列表的首部,而InnoDB则是将数据放在一个midpoint位置,通常这个midpoint为列表长度的5/8。

这种策略主要是为了避免一些不常查询的操作突然将热点数据淘汰出去,而热点数据被再次查询时,需要再次从磁盘中获取,从而影响数据库的查询性能。

如果我们的热点数据比较多,我们可以通过调整midpoint值来增加热点数据的存储量,从而降低热点数据的淘汰率。

总结

今天我带你学习了InnoDB的实现和运行原理,希望你能感受到mysql的InnoDB的设计思想,培养自己数据库性能优化的能力。

本文由 mdnice 多平台发布

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

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

相关文章

【深入浅出 Yarn 架构与实现】6-3 NodeManager 分布式缓存

不要跳过这部分知识,对了解 NodeManager 本地目录结构,和熟悉 Container 启动流程有帮助。 一、分布式缓存介绍 主要作用就是将用户应用程序执行时,所需的外部文件资源下载缓存到各个节点。 YARN 分布式缓存工作流程如下: 客户端将应用程序…

电脑——如何配置一台电脑

一、需要买那些东西 主板:显卡、电源、CPU、内存条、硬盘、显示器、鼠标、键盘、音响 怎么开始? 知乎黑虾 首先确定CPU型号再选择与该CPU兼容的主板(不同的CPU对应的主板插槽类型是不同的) 如何选择CPU型号: 主要…

HttpClient入门介绍

介绍 介绍 HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 作用: 发送HTTP请求 接收响应数据 应用场景: …

Unreal Engine11:触发器和计时器的使用

写在前面 主要是介绍一下触发器和计时器的使用; 一、在Actor中使用触发器 1. 新建一个C类 创建的C类也是放在Source文件夹中的Public和Private文件夹中;选择Actor作为继承的父类;头文件包括一个触发器和两个静态网格,它们共同…

基于SpringBoot,vue的家政服务平台的设计与实现

背景 以往的家政服务管理平台的管理,一般都是纸质文件来管理家政服务信息,传统的管理方式已经无法满足现代人们的需求;使用家政服务管理平台, 首先可以大幅提高家政服务信息检索,只需输入家政服务相关信息就能在数秒内反馈想要的…

真题详解(哈希冲突)-软件设计(七十)

真题详解(3FN)-软件设计(六十九)https://blog.csdn.net/ke1ying/article/details/130548812 在以阶段划分的编译器,____阶段的主要作用是分析构成程序的字符及由字符构造规则构成的符号是否复合程序语言的规定。 词法分析 B.语法分析 C.语义分析 D.代码…

Linux 文件系统原理 / 虚拟文件系统VFS

Linux 文件系统原理 / 虚拟文件系统VFS 虚拟文件系统 VFSVFS 定义VFS 的对象演绎超级块 super_block索引节点 inode目录项 dentry文件 file 打开文件流程参考文献 虚拟文件系统 VFS VFS 定义 VFS是一个抽象层,其向上提供了统一的文件访问接口,而向下则…

深度学习笔记之卷积神经网络(二)图像卷积操作与卷积神经网络

深度学习笔记之卷积神经网络——图像卷积操作与卷积神经网络 引言回顾:图像卷积操作补充:卷积核不是卷积函数 卷积神经网络卷积如何实现特征描述/提取卷积神经网络中的卷积核的反向传播过程场景构建与前馈计算卷积层关于卷积核的反向传播过程卷积层关于输…

《花雕学AI》新版必应 Bing 登场:轻松注册,一站式搜索、聊天与绘画应有尽有

引言: 你是否曾经在网上搜索信息时感到困惑或沮丧?你是否曾经想要在网上创造一些有趣或有用的内容,却不知道从何开始?你是否曾经想要用文字描述一个图像,却无法找到合适的图片?如果你的答案是肯定的&#x…

ChatGPT将抢占谁的工作,未来如何应对

“AI人工智能领域里程碑式应用” ChatGPT影响力已经越来越大,激起大家强烈好奇心的同时,也让一些人发出了“感觉自己快要失业了”的焦虑,今天先说一下哪些人的工作会受到 ChatGPT等AI人工智能影响 从工业时代到数字时代这100多年的发展历程来…

【华为机试】——HJ4 字符串分隔

【华为机试】——HJ5 进制转换😎 前言🙌HJ4 字符串分隔方法一:巧用scanf的输入格式方法二:循环分解思想 总结撒花💞 😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上…

泛型的特点和深浅拷贝的区别以及不相等对象的hashcode值的问题

永远都不为自己选择的道路而后悔,人生如同坐火车,风景再美也会后退,流逝的时间和邂逅的人终会渐行渐远,前行的始终是自己 泛型常用特点 泛型是JavaSE1.5之后的特性,《Java核心技术》中对泛型的定义是: “…

数据血缘分析工具SQLFLow自动画出数据库的 ER 模型

马哈鱼数据血缘分析器通过分析你所提供的 SQL 脚本,或者连接到数据库,可以自动画出数据库的 ER 模型,可视化表和字段的关系,帮助你迅速了解数据库的设计模型,进行高效的团队沟通。 马哈鱼通过两种途径来为你自动可视化…

MySQL中使用delete_at(时间戳)作为逻辑删除标记时如何使用MyBatis-Plus逻辑删除组件插入时间戳,以及如何解决自动填充失效的问题

背景 MySQL中使用delete_at(时间戳)作为逻辑删除标记 在业务中,使用逻辑删除是普遍做法,通常会使用一个名为deleted(0/1)的字段表示删除状态。 但是如果遇到有唯一约束,且可能反复删除和重新…

chatgpt如何引入本地知识?我们来看下emnlp 2022如何将本地图谱知识引入到任务型对话系统中

一、概述 title:Injecting Domain Knowledge in Language Models for Task-Oriented Dialogue Systems 论文地址:https://arxiv.org/abs/2212.08120 代码:GitHub - amazon-science/domain-knowledge-injection 1.1 Motivation 如何在PLM…

SIFT描述子实现

参考&#xff1a;SIFT图像匹配原理及python实现&#xff08;源码实现及基于opencv实现&#xff09; #include <iostream> #include <opencv2/opencv.hpp> #define _USE_MATH_DEFINES #include <math.h> #include <numeric>float mod_float(float x, f…

YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析

前言 最近我在研究YOLOv5的改进&#xff0c;一个模型的好坏、改进后效果如何都是需要一系列指标来判断的。这篇就是我将这几天学到的内容做一下总结。 友情提醒&#xff1a;本篇干货较多&#xff0c;建议先再慢慢看噢&#xff01; ​ &#x1f340;本人YOLOv5源码详解系列&…

大规模并行处理架构Doris入门操作

目录 1 基本概念1.1 Row & Column1.2 Tablet & Partition 2 创建用户2.1 创建数据库并赋予权限2.2 Doris 建表、数据导入与删除 3 建表&#xff08;Create Table&#xff09;3.1 字段类型3.2 数据划分3.3 关于 Partition 和 Bucket 的数量和数据量的建议3.4 演示单分区…

UML状态图详解

上篇文章&#xff0c;介绍了UML的基础知识&#xff0c;并详细介绍了UML中类图的知识点与画法。 本篇&#xff0c;来继续介绍UML中的另一种图——状态图。 1 UML状态图简介 状态图&#xff0c;显示一个状态机&#xff0c;属于UML活动图。 UML具有许多不同类型的图表&#xff…

<代码分享> 分支定界算法的 Python 代码框架

本文以求解整数规划模型为例&#xff0c;提供分支定界算法的 Python 代码框架&#xff0c;期待完善、指正和交流。 文件结构 具体代码 problem.py 定义问题的格式&#xff1a; from typing import Listclass Problem(object):"""problem"""de…