mysql中InnoDB的表空间--系统表空间

大家好。上篇文章我们讲了InnoDB的独立表空间,我们知道了表空间被划分为许多连续的区,对于大小为16KB的页面来说,每个区默认由64个页组成,每256个区为一组,每个组最开始的几个页的类型是固定的。(在这里强烈建议在看本篇文章之前先看一下上一篇文章)今天我们再来聊一聊–系统表空间。

系统表空间的结构和独立表空间基本类似,只不过由于整个MySQL进程只有一个系统表空间,在系统表空间中会额外记录一些有关整个系统信息的页面,所以会比独立表空间多出一些记录这些信息的页面。具体结构如下图所示:
图片
我们可以看出系统表空间和独立表空间的前三个页面(页号分别为0、1、2,类型分别是FSP_HDR、IBUF_BITMAP、INODE)的类型是完全一样的,只是页号为3~7的页面是系统表空间特有的,这些多出来的页面功能如下所示:

页号页面类型英文描述描述
3SYSInsert Buffer Header存储Insert Buffer的头部信息
4INDEXInsert Buffer Root存储Insert Buffer的根页面
5TRX_SYSTransction System事务系统的相关信息
6SYSFirst Rollback Segment第一个回滚段的页面
7SYSData Dictionary Header数据字典头部信息

除了这几个记录系统属性的页面之外,系统表空间的extent1和extent 2这两个区被称为 Doublewrite buffer ,也就是双写缓冲区。

今天我们先聊一下InnoDB数据字典,其余的概念之后咱们聊。

InnoDB数据字典

每当我们向一个表中插入一条记录的时候,mysqld都要校验插入语句对应的表存不存在,插入的列和表中的列是否符合,如果语法没有问题的话,还需要知道该表的聚簇索引和所有二级索引对应的根页面是哪个表空间的哪个页面,然后把记录插入对应索引的B+树中。所以说,MySQL 除了保存着我们插入的用户数据之外,还需要保存许多额外的信息,比如:

某个表属于哪个表空间,表里边有多少列;

表对应的每一个列的类型是什么;

该表有多少索引,每个索引对应哪几个字段;

该索引对应的根页面在哪个表空间的哪个页面;

该表有哪些外键,外键对应哪个表的哪些列;

某个表空间对应文件系统上文件路径是什么。

这些数据并不是插入的用户数据而是为了更好的管理用户数据而不得 已引入的一些额外数据,这些数据也称为元数据。InnoDB存储引擎特意定义了一系列的内部系统表(internal system table)来记录这些这些元数据,内部系统表有以下几种:

表名描述
SYS_TABLES整个InnoDB存储引擎中所有的表的信息
SYS_COLUMNS整个InnoDB存储引擎中所有的列的信息
SYS_INDEXES整个InnoDB存储引擎中所有的索引的信息
SYS_FIELDS整个InnoDB存储引擎中所有的索引对应的列的信息
SYS_FOREIGN整个InnoDB存储引擎中所有的外键的信息
SYS_FOREIGN_COLS整个InnoDB存储引擎中所有的外键对应列的信息
SYS_TABLESPACES整个InnoDB存储引擎中所有的表空间信息
SYS_DATAFILES整个InnoDB存储引擎中所有的表空间对应文件系统的文件路径信息
SYS_VIRTUAL整个InnoDB存储引擎中所有的虚拟生成列的信息

这些系统表也就是所谓的数据字典,它们都是以B+树的形式保存在系统表空间的某些页面中,其中 SYS_TABLES 、SYS_COLUMNS 、 SYS_INDEXES、SYS_FIELDS 这四个表最为重要,称之为基本系统表(basic system tables),我们先看看这4个表的结构:

SYS_TABLES表

列名描述
NAME表的名称
IDInnoDB存储引擎中每个表都有一个唯一的ID
N_COLS该表拥有列的个数
TYPE表的类型,记录了一些文件格式、行格式、压缩等信息
MIX_ID已过时,忽略
MIX_LEN表的一些额外的属性
CLUSTER_ID未使用,忽略
SPACE该表所属表空间的ID

这个SYS_TABLES表有两个索引:以NAME列为主键的聚簇索引以ID列建立的二级索引

SYS_COLUMNS表

列名描述
TABLE_ID该列所属表对应的ID
POS该列在表中是第几列
NAME该列的名称
MTYPE主数据类型
PRTYPEprecise type,精确数据类型
LEN该列最多占用存储空间的字节数
PREC该列的精度,不过这列貌似都没有使用,默认值都是0

SYS_COLUMNS表只有一个聚集索引:以(TABLE_ID, POS)列为主键的聚簇索引

SYS_INDEXES表

列名描述
TABLE_ID该索引所属表对应的ID
IDInnoDB存储引擎中每个索引都有一个唯一的ID
NAME该索引的名称
N_FIELDS该索引包含列的个数
TYPE该索引的类型,比如聚簇索引、唯一索引、普通的二级索引等
SPACE该索引根页面所在的表空间ID
PAGE_NO该索引根页面所在的页面号
MERGE_THRESHOLD如果页面中的记录被删除到某个比例,就把该页面和相邻页面合并,这个值就是这个比例

SYS_INEXES 表只有一个聚集索引:以(TABLE_ID, ID) 列为主键的聚簇索引

SYS_INDEXES表

列名描述
INDEX_ID该索引列所属的索引的ID
POS该索引列在某个索引中是第几列
COL_NAME该索引列的名称

这个SYS_INEXES 表只有一个聚集索引:以(INDEX_ID, POS) 列为主键的聚簇索引

Data Dictionary Header 页面

只要有了上述4个基本系统表,我们就可以获取其他系统表以及用户定义的表的所有元数据。

比方说我们想看看SYS_TABLESPACES 这个系统表里存储了哪些表空间以及表空间对应的属性,我们可以执行下面操作:

到SYS_TABLES 表中根据表名定位到具体的记录,就可以获取到 SYS_TABLESPACES 表的TABLE_ID。

使用这个TABLE_ID到SYS_COLUMNS表中就可以获取到属于该表的所有列的信息。

使用这个TABLE_ID还可以到SYS_INDEXES表中获取所有的索引的信息,索引的信息中包括对应的INDEX_ID,还记录着该索引对应的B+树根页面是哪个表空间的哪个页面。

使用INDEX_ID 就可以到SYS_FIELDS表中获取所有索引列的信息。

那么这4个表的元数据去哪里获取呢?原来这4个表的元数据信息硬编码到了代码中,然后InnoDB用一个固定的页面来记录这4个表的聚簇索引和二级索引对应的B+树位置,这个页面就是页号为7的页面,类型为SYS,记录了Data Dictionary Header ,也就是数据字典的头部信息。除了这4个表的5个索引的根页面信息外,这个页号为7的页面还记录了整个InnoDB存储引擎的一些全局属性,如下图所示:

在这里插入图片描述

这个页面由下边几个部分组成:

名称占用空间简单描述
File Header(文件头部)38 字节页的一些通用信息
Data Dictionary Header(数据字典头部信息)52 字节记录一些基本系统表的根页面位置以及InnoDB存储引擎的一些全局信息
Unused4 字节
Segment Header(段头部信息)10 字节记录本页面所在段对应的INODE Entry位置信息
Empty Space(尚未使用空间)16272字节用于页结构的填充,没啥实际意义
File Trailer(文件尾部)8 字节校验页是否完整

可以看到这个页面里有Segment Header 部分,意味着InnoDB把这些有关数据字典的信息当成一个段来分配存储空间。由于需要记录的数据字典信息非常少(可以看到Data Dictionary Header 部分仅占用了56字节),所以该段只有一个碎片页,也就是页号为7的这个页。

接下来我们聊一聊Data Dictionary Header部分的各个字段:

Max Row ID : 如果我们建表时没有定义主键,而且表中也没有 UNIQUE 索引,那么InnoDB存储引擎会默认生成一个名为row_id 的列作为主键。因为它是主键,所以每条记录的row_id列的值不能重复。在拥有 row_id列的表插入一条记录时,该记录的row_id列的值就是Max Row ID 对应的值,然后再把 Max Row ID 对应的值加1,也就是说这个Max Row ID 是全局共享的。

Max Table ID : InnoDB存储引擎中的所有的表都对应一个唯一的ID,每次新建一个表时,就会把本字段的值+1,然后作为该表的ID。

Max Index ID : InnoDB存储引擎中的所有的索引都对应一个唯一的ID,每次新建一个索引时,就会把本字段的值+1,作为该索引的ID。

Max Space ID : InnoDB存储引擎中的所有的表空间都对应一个唯一的ID,每次新建一个表空间时,就会把本字段的值+1,作为该表空间的ID。

Mix ID Low(Unused) : 这个字段没啥用,跳过。

Root of SYS_TABLES clust index : 表示SYS_TABLES表聚簇索引的根页面的页号。

Root of SYS_TABLE_IDS sec index : 表示SYS_TABLES表为ID列建立的二级索引的根页面的页号。

Root of SYS_COLUMNS clust index : 表示SYS_COLUMNS表聚簇索引的根页面的页号。

Root of SYS_INDEXES clust index: 表示SYS_INDEXES表聚簇索引的根页面的页号。

Root of SYS_FIELDS clust index : 表示SYS_FIELDS表聚簇索引的根页面的页号。

information_schema 系统数据库

用户是不能直接访问InnoDB 的这些内部系统表的,但是InnoDB在系统数据库 information_schema 中提供了一些以 innodb_sys 开头的表。
在这里插入图片描述

在information_schema 数据库中的这些以 INNODB_SYS 开头的表并不是真正的内部系统表(内部系统表就是上边说的以SYS 开头的那些表),而是在存储引擎启动时读取这些以SYS开头的系统表,然后填充到这些以 INNODB_SYS 开头的表中。

好了,今天的内容到这里就结束了,有什么疑问欢迎在评论区进行讨论。最后依旧是请各位老板有钱的捧个人场,没钱的也捧个人场,谢谢各位老板!

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韩朝洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值