Code前端首页关于Code前端联系我们

MySQL InnoDB如何工作:底层如何存储数据?

terry 2年前 (2023-09-26) 阅读数 52 #数据库

MySQL InnoDB工作原理:底层如何存储数据?开始阅读本文之前,先思考三个问题:

  1. innodb基础层是如何存储数据的?
  2. 表格中的隐藏列是什么?
  3. 用户注释如何交互?

请阅读以下内容并给出您的答案。

本文主要包含以下内容:MySQL InnoDB工作原理:底层如何存储数据?

1.磁盘还是内存?

1.1磁盘

如何解决数据安全问题?

答案:将数据存储在磁盘上。

只要磁盘不损坏,数据就可以永久保存。

如果每次都从磁盘读取数据,数据会安全,但是频繁的IO请求会影响数据库的性能。

那么我们如何解决数据库性能问题呢?

1.2 内存

将数据存储在内存中。

内存可以满足我们快速读写数据的需求。

内存可以存储部分用户数据,但如果数据量太大,可能无法存储所有用户数据。此外,如果数据库服务器或部署节点崩溃或重新启动,则存在数据丢失的风险。

如何防止异常情况导致数据丢失。同时,能否保证数据读写的速度?

2。数据页

页是mysql中磁盘和内存交换的基本单位,也是mysql存储空间管理的基本单位。

同一数据库实例中的所有表空间具有相同的页大小;默认情况下,桌面上的页面大小为 16KB。当然,也可以通过更改 innodb_page_size 选项来更改默认大小。需要注意的是,不同的页面大小最终会导致不同的尺寸。

一次从磁盘读取至少16KB的内容到内存,一次从内存刷新至少16KB的内容到磁盘。

如下图书写时:

MySQL InnoDB工作原理:底层如何存储数据?

如下图阅读时:

MySQL InnoDB工作原理:底层如何存储数据?

数据页主要用于存储表格中的注释。它使用双向链表链接在磁盘上。方便搜索,您可以快速从一个数据页导航到另一页。

很多时候,因为我们的表中有很多数据,所以可能会在磁盘上存储很多页数据。

如果我们想要根据一定的条件查询数据,我们需要从一个数据页中找到另一个数据页。这时,双向链表就派上用场了。磁盘上每个数据页的整体结构如下图所示:

MySQL InnoDB工作原理:底层如何存储数据?

一个数据页的内容是什么?

MySQL InnoDB工作原理:底层如何存储数据?

从上图可以看到,数据页主要包含以下几个部分:

  • 文件头
  • 页头
  • 最大和最小记录 ”s♷可用空间 目录页
  • 文件尾部

3。用户记录

对于新申请的数据页,用户记录为空。在插入数据时,innodb会分配一部分空白空间用于用户记录。

用户记录是innodb的重中之重。通常存储在数据库中的数据是在内部存储的。那么,它包含什么?

实际上,innodb 支持四种数据行格式:

  1. 紧凑行格式
  2. 冗余行格式
  3. 动态行格式 ♻‷紧凑行格式 ♻‷格式例如:

    MySQL InnoDB工作原理:底层如何存储数据?

    Recor d user主要包含三部分:

    1. 附加信息记录,其中包括变长字段、空值列表和记录头信息。
    2. 隐藏列,包含行id、事务id和断点。
    3. 真实数据字段包含真实的用户数据,并且可以有很多字段。

    我们一起来看看内容吧。

    3.1 附加信息

    附加信息不是实际的用户数据,它用于帮助数据存储。

    3.1.1 变长列列表

    有些数据如果直接存储的话会出现问题。例如:如果列是varchar或text类型,则其长度不固定,可以根据存储数据的长度而变化。相应地改变。

    如果没有在一处记录正确的数据长度,innodb将不知道要分配多少空间。如果按照固定长度分配空间,但实际数据占用的空间并不多,那不是浪费吗?

    因此,应在变长列中记录特定变长列所占用的字节数,以方便所需的空间分配。

    3.1.2 空值列表

    数据库中某些列的值允许为空。如果每个字段的空值都存储在用户记录中,显然是浪费存储空间。

    有没有办法只标记它而不存储实际的空值?

    答案:将空字段保存到空值列表中。

    列表中使用二进制值1表示该列允许为空,使用0表示不允许为空。它只占用1位来指示某个字符是否为空,确实可以节省大量的存储空间。

    3.1.3 记录头信息

    记录头信息用于描述一些特殊属性。

    MySQL InnoDB工作原理:底层如何存储数据?

    主要包括:

    • deleted_flag:删除标志,用于表示一条记录已被删除。
    • min_rec_flag:最小目录标志,即非叶子节点上的最小目录标志。
    • n_owned:拥有的记录数,记录该组中索引记录的数量。
    • heap_no:在堆中的位置,表示记录当前在堆中的位置。
    • record_type:记录类型,其中:0表示普通记录,1表示非叶子节点,2表示Infrimum记录,3表示Supremum记录。
    • next_record:下一个记录位置。

    3.2 隐藏字段

    数据库在存储用户记录时,会自动创建一些隐藏字段。如下图所示:

    MySQL InnoDB工作原理:底层如何存储数据?

    现在innodb自动创建了三个隐藏列:

    • db_row_id,即行id,即记录的唯一标识符。
    • db_trx_id,事务id,是事务的唯一标识符。
    • db_roll_ptr,回滚点,用于事务回滚。

    如果表中有主键,则使用主键作为行ID,无需额外创建。如果表中没有主键,如果有非空唯一键,​​则将其作为行ID,无需创建添加。

    如果表中没有主键或唯一键,数据库会自动生成行id。

    也就是说,在innodb中,隐藏列中的事务id重放点应该根据隐藏条件创建。 。

    3.3 真实数据字段

    真实数据字段存储用户的真实数据,可以包含多个字段的数据。这个很简单,不多说。

    3.4 用户记录如何关联?

    通过上面的内容,大家应该对如何保存用户记录有了一定的了解。

    但有一个问题,一条用户记录如何连接到另一条用户记录? innodb如何知道特定记录的下一条记录是谁?

    答:用前面提到的,记录附加信息》记录头信息》下一个记录位置。

    MySQL InnoDB工作原理:底层如何存储数据?

    许多用户记录通过下一个记录位置形成单向链表。这样就可以从前往后查到所有的记录了。

    4。最大和最小记录

    从上面可以看到,在数据页面上,如果有多条用户记录,它们通过连接到下一个记录位置

    但是有一个问题:如果我们能找到最大记录和最小记录怎么办?

    这需要在保存用户记录时保留最大和最小记录。

    最大记录存储在 Supremum 记录中。

    在 Infimum 记录中保存最少的记录。

    存储用户记录时,数据库会自动创建两条附加记录:Supremum 和 Infimum。关系如下图所示:

    MySQL InnoDB工作原理:底层如何存储数据?

    从图中可以看出,用户数据从最小的记录开始,传递到下一个记录位置,从小到大逐步查找,最后找到最大的记录。

    5。页目录

    为了提高扫描所有用户数据页的效率,InnoDB创建了一个类似于书籍目录的页目录。

    页目录过程:

    1. 将所有正常记录(包括最大和最小记录,不包括标记为已删除的记录)分为几组。
    2. 每组的最后一条记录头信息(即该组中最大的记录)列出了该组中的记录数。
    3. 分别从每组最后一条记录中提取偏移地址,并按顺序存储在靠近页尾的地方。这个地方称为页面目录。页目录中的这个地址偏移量称为槽,因此页目录是由槽组成的。

    可以看到页面的目录由很多槽位组成。如下图所示:

    MySQL InnoDB工作原理:底层如何存储数据?

    这样就可以通过二分查找的方式快速找到需要查找的记录。

    注意:

    最小记录所在组只能有1条记录,最大记录所在组的记录数只能在1到8之间,其余组的记录数只能是 4 到 8 项。

    6。文件头和尾部

    6.1 文件头

    通过行记录中下一条记录的位置页目录速度太快,无法记录但是有一个前提,即也就是说,用户记录必须存在于同一数据页上。

    用户记录较多,在第一个数据页找不到自己想要的数据,需要到另一个页面查找怎么办?

    现在,您需要使用头文件

    头文件包含了页面的一些通用信息,包含固定的38字节。它由以下内容组成:

    MySQL InnoDB工作原理:底层如何存储数据?

    innodb 通过页码、上一页码、下一页码来连接不同的数据页。如下图所示:

    MySQL InnoDB工作原理:底层如何存储数据?

    不同数据页之间,上一页页码和下一页页码构成双向链表。这样就可以从前到后逐页查找所有数据。

    另外,页面类型也是一个非常重要的栏目,它包含的类型很多。比较著名的有:数据页、索引页(目录入口页)、溢出页、撤消日志页等。从数据页。如果数据有更新,需要刷新到磁盘。

    如果程序刷新到磁盘时出现异常,例如:进程死掉,那么只能更新部分数据。我们如何确定最后一次更新数据何时完成?

    这需要在文件末尾添加

    这列出了页面中的 校验和

    检查页是在数据刷新到磁盘之前计算的。如果稍后更新数据,则会计算新值。该校验和也将记录在文件头中。由于文件头在前面,所以会先刷新到磁盘。

    接下来刷新用户记录到磁盘时,比如再次更新该段,程序就不正常了。此时,文件末尾的校验和仍然是旧值。数据库会验证文件末尾的校验和不等于文件头部的新值,表明数据页中的数据不完整。

    7。页头

    通过上述内容,可以方便地访问数据页,但是还有一个更重要的问题,就是记录的状态信息。

    出于性能原因,数据页状态信息被收集并存储在页头中。

    页面标题由14部分组成,共56字节。它由以下内容组成:

    MySQL InnoDB工作原理:底层如何存储数据?

    摘要

    多个数据页通过页码形成双向链表。在每个数据页上的数据行之间,由下一个记录位置创建一个单链表。整体架构图如下:

    MySQL InnoDB工作原理:底层如何存储数据?

    来源:Data and People

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门