MySQL InnoDB 存储引擎的底层逻辑架构

目录
  • 正文
  • 内存架构
    • 1. 自适应哈希索引
    • 2. Buffer pool
    • 3. Change buffer
    • 4. Log Buffer
  • 磁盘架构
    • 1. 系统表空间
    • 2. 独立表空间
    • 3. 普通表空间
    • 4. Undo 表空间
    • 5. 临时表空间
  • 总结

正文

我们都知道 MySQL 数据库有很多个存储引擎,其中另我们印象深刻的应该是 InnoDB 存储引擎,它从 MySQL 5.5 之后就是默认的存储引擎,它有支持事务、行级锁、MVCC 以及外键等优点。

那么你知道InnoDB存储引擎的底层逻辑架构吗?下面我们就来聊一下InnoDB存储引擎。

InnoDB存储引擎主要由两个部分组成,分别是内存架构磁盘架构,这两个部分都有自己不可或缺的功能。下面我们就通过一张图来详细了解一下这两个部分。

内存架构

内存架构(英文名称:In-Memory Structures),在InnoDB存储引擎中主要包括四个部分,分别是自适应哈希索引、Buffer poolChange bufferLog Buffer四个部分。

1. 自适应哈希索引

首先我们来聊聊自适应哈希索引,自适应哈希索引的英文名称:Adaptive Hash Index它的设计目的是想让 MySQL 数据库像内存数据库一样高效,同时不会丢掉事务、行锁以及外键等特性

它并不是我们人为去创建的,而是InnoDB存储引擎通过索引监控机制去自动创建的,也就是说如果InnoDB存储引擎监控到自适应哈希索引可以提高查询速度,随即InnoDB存储引擎会自动为本次查询创建自适应哈希索引。命中了自适应哈希索引的查询就不会触发全表扫描,而是直接通过索引拿需要的数据,这样就可以提高数据库的查询速度。

但是自适应哈希索引并不是任何情况下都可以使用,例如:link '%xxx',这是因为 link 前置百分号查询本身就需要全表扫描,所以用与不用索引的结果都是一样的,用索引反而会多此一举,因此这种情况下不需要创建自适应哈希索引。

2. Buffer pool

Buffer pool(中文名称:缓冲池),是 MySQL 数据库中最重要的一个部分。在数据库启动之时,首先会初始化这块内存区域,它占用了 MySQL 数据库总内存空间的80%以上。详细情况可以通过show engine innodb status\G来查看:

mysql> show engine innodb status\G
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 301572
Buffer pool size   8191
Free buffers       6916
Database pages     1252
Old database pages 442
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 258, not young 1
0.00 youngs/s, 0.00 non-youngs/s
Pages read 320, created 938, written 3279
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1252, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

它的主要作用是提高数据库查询的效率,其中主要使用了LRU算法,下面我们一起来详细了解一下LRU算法。

MySQL数据库中,LRU算法的底层主要是一个链表。不过该链表被分为了两个区域,分别是新子链表和旧子链表,而且新子链表占用总空间的5/8,旧子链表占用总空间的3/8。其主要实现的步骤如下:

  • 第一步:假设我们读取数据2,这个时候恰好数据2在新子链表中,这个时候,会将数据2调换至新子链表的开头。
  • 第二步:如果查询一条buffer pool中没有的数据时,MySQL数据库将在磁盘中读取出该条数据数据X,并且插入新子链表后面,同时会淘汰旧子链表中的数据N

说到这里,可能就会有朋友问了,既然新数据移到链表的最前方,排列在最后面的数据直接淘汰,那么为什么还需要一个新子链表和旧子链表呢?

这个时候我们设想一下,假设我们查询一个比较大的数据,可能会占满所有的Buffer pool内存空间,按照我们理解的淘汰策略,这个时候会一下子将所有的数据全部淘汰。而这个时候正在高速运转的数据库会将所有的查询全部作用于磁盘,那将会导致系统磁盘 IO 急剧升高且数据库反应缓慢,最终会导致用户体验下降。

这个时候我们再看,如果把所有新查询的数据全部存放于新子链表中,查询的数据最多把新子链表中的空间全部占满而旧子链表中仍然保留着之前的数据,对于高速运转的数据库来讲,就不会导致系统磁盘 IO 急剧升高和数据库反应缓慢了。这也正是新旧子链表设计的初衷。

Buffer Pool存储块中还保留有一个小内存块,即Change buffer。下面我们就来聊聊这块内存是用来做什么的。

3. Change buffer

Change Buffer的另一个名字叫“写缓存”。见名知意,Change Buffer主要的功能是记录数据库的数据修改操作的结果的。主要目的是提高数据库的写性能

下面我们就来详细分析一下,数据修改操作的步骤。

  • 第一步:修改一条数据时,首先判断该条数据是否存在于Buffer Pool之中。

    • 如果在,直接修改Buffer Pool中的相关数据。
    • 如果不在,首先在磁盘中读取该条数据到Change Buffer之中,而后在Change Buffer中修改该数据,同时写入Redo Log之中(为了防止数据丢失),等下一次查询该条数据时,合并至Buffer Pool中。
  • 第二步:Change Buffer中数据修改之后,什么时候合并数据呢?
    • 第一种方式:当修改的这条数据被查询的时候,合并到Buffer Pool
    • 第二种方式:MySQL 数据库中的Master Thread合并(周期默认:10s)。
    • 第三种方式:当 MySQL 数据库关闭时,通过Redo Log合并到磁盘中。

Change Buffer之所以这样设计,是因为对于高速运转的 MySQL 数据库来讲,如果每一次修改都修改磁盘同时又修改Buffer Pool中的内容的话,对于 MySQL 数据库来讲代价太大了,磁盘的 IO 也会非常高,最终会导致 MySQL 数据库运行缓慢。那么,修改数据时使用Change Buffer相当于在内存中修改数据,并且保存在内存中,当数据库空闲时才会写入磁盘,这样既能够达到修改数据的目的,又能够降低数据库对于系统的性能要求,进而提高数据库的性能。

上面我们提到,Change Buffer修改完成之后,会修改redo log中的数据,那么接下来我们就来了解一下Log Buffer

4. Log Buffer

我们设想一下,如果在Change Buffer修改完数据之后,仅仅保存在内存中,那么如果这个时候数据库宕机,也就意味着我们刚刚修改的数据也随即丢失,而这一点是不能被允许的。

怎么解决这个问题呢?MySQL 给我们提供了一种写日志的方案,也就是说,修改完的数据会保存到一个叫Redo Log(具体请参考下方的Redo Log部分)的日志中。它是一个物理日志,当数据宕机时,它会将数据直接保存在磁盘之上;当数据库开启时,自动写入到数据库的磁盘中,以至于数据不会丢失。

上方我们提到了,Redo Log是一个物理日志,如果把大量的数据直接写进磁盘,还是会导致数据库性能低下,我们用一个Log Buffer来保存需要写入Redo log的数据,这样有利于提高数据库的性能。

这个时候你可能会问:那Change Buffer为什么不直接写入磁盘呢?

具体情况是这样的,MySQL 数据库在系统磁盘上保存的数据是有序的(典型就是按照主键 ID),如果每一次修改数据直接操作磁盘的话,会导致很多数据的位置发生更改(也就是我们常说的:随机 IO),但是Redo log中保存的数据是无序的,随意不会产生随机 IO,所以使用Redo log暂时保存数据是确保数据不丢失时的最好办法。

聊完InnoDB存储引擎的内存架构之后,接下来我们再来了解一下InnoDB存储引擎的磁盘架构。

磁盘架构

对于InnoDB存储引擎来说,磁盘架构最重要的就是表空间了。InnoDB存储引擎的表空间主要分为:系统表空间、独立表空间、普通表空间、Undo表空间以及临时表空间。

下面我们一起来详细聊聊InnoDB存储引擎的磁盘架构中的各个表空间。

1. 系统表空间

系统表空间是InnoDB存储引擎中最重要的表空间之一,它的主要作用是存储InnoDB数据字典、双写缓冲、更改缓存以及撤销日志。

系统表空间一般存放于 MySQL 数据库目录中,名称为:ibdata1。系统表空间一般不一定只有一个,也可能有多个,系统表空间的大小和数量由innodb_data_file_path控制。具体如下:

mysql> SHOW VARIABLES LIKE 'innodb_data_file_path';
+-----------------------+------------------------+
| Variable_name         | Value                  |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
+-----------------------+------------------------+
1 row in set (0.00 sec)

在这里特别需要说明的是,InnoDB 数据字典在 MySQL 8.0 版本以后合并至 MySQL 数据字典中了,不再存储在系统表空间中了。

这个时候你可能会问,MySQL 数据表中的数据存放于哪里呢?下面我们就来聊一聊这个问题。

2. 独立表空间

对于innodb存储引擎来说,我们通常创建数据表的时候,会在 MySQL 数据目录中创建两个文件,分别是.ibd.frm两个文件。.ibd文件主要用来存储表数据,而.frm文件主要用来存储索引。

这种做法可以将所有的数据表分开管理,也能够实现快速数据迁移,当数据出现故障之时也可以提高数据恢复的成功率。不过这样的做法又会增加磁盘的碎片,对系统处理表文件的性能有一定的影响。

3. 普通表空间

普通表空间的本质其实就是一个共享的表空间。其具体文件在 MySQL 数据库的数据目录中是以.ibd结尾的文件。跟系统表空间类似,它支持所有 MySQL 数据库中的数据表的结构,它是将数据库的一些元数据保存在内存之中,进而能够减少独立表空间对于内存的消耗。

4. Undo 表空间

Undo 表空间主要是用来保存撤销日志(即:Undo Log)的空间。它默认情况下存储在 MySQL 数据库的根目录。我们可以通过以下方式来查看:

mysql> SHOW VARIABLES LIKE 'innodb_undo_directory';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_undo_directory    | ./    |
+--------------------------+-------+
4 rows in set (0.00 sec)

MySQL 8.0版本之后,undo 表空间会在 MySQL 数据库的数据根目录生成 undo_001 和 undo002 共两个文件。

5. 临时表空间

临时表空间主要是用来保存数据库会话中的临时数据的。在 MySQL 数据库的数据根目录中保存以ibtmp1命名的文件。最主要的是我们在使用 join 连表查询的时候,会在临时表空间内创建临时数据表用来辅助查询。我们可以通过以下方式来查看临时表空间的配置:

mysql> SELECT @@innodb_temp_data_file_path;
+------------------------------+
| @@innodb_temp_data_file_path |
+------------------------------+
| ibtmp1:12M:autoextend        |
+------------------------------+
1 row in set (0.00 sec)

总结

InnoDB存储引擎是 MySQL 数据库中最重要的一个存储引擎之一。今天我们一起通过它的内存架构和磁盘架构深入地了解了它的底层架构。

在内存架构中,自适应哈希索引有利于提高查询速度;Buffer pool主要提供了一个内存池,将经常查询的数据存放于内存中,这样做有利于提高数据库的查询性能和降低系统的磁盘 IO;Change buffer主要是将修改好的数据存放于内存之中,下一次查询的时候合并到Buffer pool之中,这样做的好处是可以降低修改数据时的磁盘 IO,进而提高数据库的性能;Log Buffer是将所有修改的数据存放在其中,之后写入到Redo Log之中,防止数据丢失。

在磁盘架构中,系统表空间是用来修改和撤销日志的地方,之前的数据库版本中还存放InnoDB数据字典以及双写缓冲;独立表空间主要是用来存储表数据和索引的地方;普通表空间是一个共享的表空间,能够减少独立表空间对于内存的消耗;Undo 表空间主要作用于事务回滚的,在使用未提交之前,用来保存原来的数据,一旦事务回滚则用 Undo 表空间中的内容替换修改过后的数据,进而达到回滚的目的;临时表空间主要是一个过渡的表空间,通常的一些操作需要有这种过渡来辅助操作,例如连表查询。

从内存架构到磁盘架构,InnoDB存储引擎为我们提供了一个高性能、高安全的数据库存储引擎。通常在实际应用过程中,InnoDB存储引擎是我们的首选存储引擎,但是在使用过程中一定要把Buffer pool的空间设置得足够大,这样有利于提高数据的查询性能。

以上就是MySQL InnoDB 存储引擎的底层逻辑架构的详细内容,更多关于MySQL InnoDB 底层逻辑的资料请关注我们其它相关文章!

(0)

相关推荐

  • MySQL的存储引擎InnoDB和MyISAM

    目录 1.MyISAM底层存储 1.1MyISAM底层存储(非聚集索引方式) 1.2InnoDB底层存储(聚集索引方式) 2.InnoDB与MyISAM简介 3.MyISAM与InnoDB的比较 4.什么时候用MyISAM数据存储引擎?什么时候用InnoDB数据存储引擎? 1.MyISAM底层存储 (非聚集索引方式)与InnoDB底层存储(聚集索引方式) 1.1MyISAM底层存储(非聚集索引方式) Myisam 创建表后生成的文件有三个: frm:创建表的语句 MYD:表里面的数据文件(myi

  • Mysql InnoDB中B+树索引使用注意事项

    目录 一.根页面万年不动 二.内节点中目录项记录的唯一性 三.一个页面至少容纳 2 条记录 一.根页面万年不动 在之前的文章里,为了方便理解,都是先画存储用户记录的叶子节点,然后再画出存储目录项记录的内节点. 但实际上 B+ 树的行成过程是这样的: 每当为某个表创建一个 B+ 树索引,都会为这个索引创建一个根节点页面.最开始表里没数据,所以根节点中既没有用户记录,也没有目录项记录. 当往表里插入用户记录时,先把用户记录存储到这个根节点上. 当根节点页空间用完,继续插入记录,此时会将根节点中所有记

  • Mysql InnoDB引擎中页目录和槽的查找过程

    目录 Mysql InnoDB引擎页目录 一.页目录和槽 二.页目录的规定 三.页目录查找记录的过程 总结 Mysql InnoDB引擎页目录 一.页目录和槽 接上一篇,现在知道记录在页中按照主键大小顺序串成了单链表. 那么我使用主键查询的时候,最顺其自然的办法肯定是从第一条记录,也就是 Infrimum 记录开始,一直向后找,只要存在总会找到.这种在数据量少的时候还好说,一旦数据多了,遍历耗时一定非常长. 于是,作者又想到了一个好办法,灵感来自于书本中的目录.我们翻书的时候想查找一些内容,就会

  • Mysql InnoDB引擎中的数据页结构详解

    目录 Mysql InnoDB引擎数据页结构 一.页的简介 二.数据页的结构 三.记录在页中的存储结构 四.记录头信息 1. deleted_flag 2. min_rec_flag 3. n_owned 4. heap_no 5. record_type 6. next_record Mysql InnoDB引擎数据页结构 InnoDB 是 mysql 的默认引擎,也是我们最常用的,所以基于 InnoDB,学习页结构.而学习页结构,是为了更好的学习索引. 一.页的简介 页是 InnoDB 管理

  • Mysql InnoDB聚簇索引二级索引联合索引特点

    目录 一.聚簇索引 特点 1 特点 2 二.二级索引 三.联合索引 接上一篇内容:https://www.jb51.net/article/249934.htm 一.聚簇索引 其实之前内容中介绍的 B+ 树就是聚簇索引. 这种索引不需要我们显示地使用 INDEX 语句去创建,InnoDB 引擎会自动创建.另外,在 InnoDB 引擎中,聚簇索引就是数据的存储方式. 它有 2 个特点: 特点 1 使用记录主键值的大小进行记录和页的排序. 其中又包含了下面 3 个点: 页(包括叶节点和内节点)内的记

  • Mysql InnoDB 的内存结构详情

    目录 1 前言 2 InnoDB 存储引擎结构 2.1 InnoDB表存储引擎文件 2.2 InnoDB 预读机制 2.3 InnoDB 特性 2.3.1 插入缓存 2.3.2 二次写 (double write) 2.3.3 自适应hash索引 2.3.4 异步IO 2.3.5 刷新邻接页 3 sql 执行的逻辑 3.1 sql 执行 3.2 FreeList.LRU List 和 Flush List 1 前言 我们都熟悉mysql数据库服务架构,也清楚 sql 的执行顺序,mysql的数据

  • MySQL InnoDB 存储引擎的底层逻辑架构

    目录 正文 内存架构 1. 自适应哈希索引 2. Buffer pool 3. Change buffer 4. Log Buffer 磁盘架构 1. 系统表空间 2. 独立表空间 3. 普通表空间 4. Undo 表空间 5. 临时表空间 总结 正文 我们都知道 MySQL 数据库有很多个存储引擎,其中另我们印象深刻的应该是 InnoDB 存储引擎,它从 MySQL 5.5 之后就是默认的存储引擎,它有支持事务.行级锁.MVCC 以及外键等优点. 那么你知道InnoDB存储引擎的底层逻辑架构吗

  • MySql InnoDB存储引擎之Buffer Pool运行原理讲解

    目录 1. 前言 2. Buffer Pool 2.1 Buffer Pool结构 2.2 Free链表 2.3 缓冲页哈希表 2.4 Flush链表 2.5 LRU链表 2.6 多个实例 2.7 Buffer Pool状态信息 3. 总结 1. 前言 我们已经知道,对于InnoDB存储引擎而言,页是磁盘和内存交互的基本单位.哪怕你要读取一条记录,InnoDB也会将整个索引页加载到内存.哪怕你只改了1个字节的数据,该索引页就是脏页了,整个索引页都要刷新到磁盘.InnoDB是基于磁盘的存储引擎,如

  • 简述MySQL InnoDB存储引擎

    前言: 存储引擎是数据库的核心,对于 MySQL 来说,存储引擎是以插件的形式运行的.虽然 MySQL 支持种类繁多的存储引擎,但最常用的当属 InnoDB 了,本篇文章将主要介绍 InnoDB 存储引擎相关知识. 1. InnoDB 简介 MySQL 5.5 版本以后,默认存储引擎就是 InnoDB 了.InnoDB 是一种兼顾了高可靠性和高性能的通用存储引擎.在 MySQL 5.7 中,除非你配置了其他默认存储引擎,否则执行 CREATE TABLE 不指定 ENGINE 的语句将创建一个

  • 详解MySQL InnoDB存储引擎的内存管理

    存储引擎之内存管理 在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页. 上面的图中,我使用8个数据页来表示队列,具体作用,先卖个关子.在InnoDB存储引擎中,缓冲池中页的默认大小是16KB,LRU列表中有一个midpoint的位置,新读取到的数据页并不是直接放入到LRU列表的首部,而是放入

  • Mysql Innodb存储引擎之索引与算法

    目录 一.概述 二.数据结构与算法 1.二分查找 2.二叉查找树和平衡二叉树 1)二叉查找树 2)平衡二叉树 三.B+树 1.B+树完整定义 2.关于 M 和 L的选定案例 四.B+树索引 1.聚集索引 2.辅助索引 五.关于 Cardinality 值 1.Cardinality定义 2.Cardinality的更新 六.B+树索引的使用 1.联合索引 2.覆盖索引 3.优化器选择不使用索引的情况 4.索引提示 5.Multi-Range Read 优化 (MRR) 6.Index Condi

  • MySQL InnoDB存储引擎的深入探秘

    前言 在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用,主要特点有:支持事务.行锁设计支持高并发.外键支持.自动崩溃恢复.聚簇索引的方式组织表结构等. 体系架构 InnoDB存储引擎是由内存池.后台线程.磁盘存储三大部分组成. 线程 InnoDB 使用的是多线程模型, 其后台有多个不同的线程负责处理不同的任务 Master Thread Maste

  • MySQL 学习总结 之 初步了解 InnoDB 存储引擎的架构设计

    一.存储引擎 上节我们最后说到,SQL 的执行计划是执行器组件调用存储引擎的接口来完成的. 那我们可以理解为:MySQL 这个数据库管理系统是依靠存储引擎与存放数据的磁盘文件进行交互的. 那么 MySQL 有哪些存储引擎呢? 主要有 MyISAM.InnoDB.Memory等等.而现在互联网中,基本都是使用 InnoDB 存储引擎,所以接下来我将简单总结自己关于 InnoDB 存储引擎的学习,比较简单的介绍 InnoDB 存储引擎里面的组件. 二.缓冲池 我们现在都知道了,数据库的数据是存放在磁

  • InnoDb 体系架构和特性详解 (Innodb存储引擎读书笔记总结)

    后台线程 •Master Thread 核心后台线程,主要负责将缓冲池的数据异步刷新到磁盘.例如脏页的刷新,插入缓冲的合并,undo 页的回收等. 每秒一次的操作: 1.日志缓冲刷新到磁盘,即使该事务还没有提交.该操作总是会发生,这个就是为了再大的事务,提交时间都很短. 2.当IO压力很小时(1s内发生的IO次数小于5% innodb_io_capacity)合并5% innodb_io_capacity 的插入缓冲. 3.当脏页比例大于 innodb_max_dirty_pages_cnt,

  • MySQL中InnoDB存储引擎的锁的基本使用教程

    MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 各种锁特点 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生冲突的概率最高,并发度最低 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高 页面锁:开销和加锁时间介于表锁和行锁之间:会出现死锁:锁定粒度介于表锁和行锁之

  • 详解MySql中InnoDB存储引擎中的各种锁

    目录 什么是锁 InnoDB存储引擎中的锁 锁的算法 行锁的3种算法 幻像问题 锁的问题 脏读 不可重复读 丢失更新 死锁 什么是锁 现实生活中的锁是为了保护你的私有物品,在数据库中锁是为了解决资源争抢的问题,锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访. 数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性 InnoDB存储引擎区别于MyISAM的两个重要特征就是:InnoDB存储引擎支持事务和行级别的锁,MyISAM只支持表级别的锁 In

随机推荐