2.InnoDB的存储结构

InnoDB 系列文章目录

1.InnoDB的关键特性
2.InnoDB的存储结构
3.InnoDB的索引和算法
4.InnoDB的锁总结
5.InnoDB的事务

上一篇文章
1.InnoDB的关键特性
介绍了InnoDB的四大特性,这篇文章介绍下InnoDB的存储结构。

一 物理文件

首先,先打开mysql的数据存储路径,可以使用命令查看具体的路径。
如果是使用Navicat Premiun,可以直接按下F6打开命令界面。

show global variables like "%datadir%";
表空间文件 ibd

可以看到里面有一些文件,其中以ibd为后缀的文件,就是存放数据和索引以及一些其他数据,称之为表空间。如果将innodb_file_per_table 设置为ON(默认),那么每个表都有一个独立的表空间,打开mydata文件,可以看到以表命名的ibd文件。

除了ibd,还有一些日志文件,如二进制日志:binlog.xxxxx,参数文件,表定义文件等。

二 逻辑结构

既然知道了数据的物理文件,那么表空间内的逻辑机构又是如何呢?

表空间了包含了多个段,常见的包括索引段,数据段,回滚段。索引段存储了非聚集索引,而数据段其实是按照聚集索引存储的数据,所以可以理解为格式是一样的。
每个段中包含了区和32个页,一般先使用页,当页使用完了才使用区,防止每次创建一些数据时,需要申请很大的一个区的空间。

区是由64个连续的页组成的,每个页16KB,所以一个区就是1MB。最多可以申请4个区以保证数据的连续性。

页是具体存储数据的单位,实际上索引并没有找到对应的数据的行,而是找到对应数据的行所在的页。然后把页加载到缓冲区后,使用二分法查找对应的行数据。
页可以存储数据,也可以存储UNDO,索引,还有大对象。

行就是我们一般理解的数据库中的一行数据,存放在页内,一页存放16KB的数据,也就是2~200行。

三 行记录格式

介绍完InnoDB数据存储的段区页行,再介绍下行的具体格式。
InnoDB又两种存储数据的行格式,Compact和Redundant,Redundant时为了兼容之前的版本而保留的。

1.Compact格式

Compact行数据格式分为四个部分

  • 变长字段长度列表
    变长字段长度列表记录了变长字段(varchar)的长度,并且是以倒序存放的。每一个变长字段最长用两个字节表示,所以varchar的最长长度是65535(2^16-1)。但是实际上,如果创建一个varchar(65535)的字段时,会发现mysql有警告,而且在非严格模式下,会发现该字段的类型被转换为text。那是因为实际上还有其他的消耗。实际上能创建的最大的长度是65532.

  • NULL标志位
    NULL标志位,标记哪个字段的值为空。有没有好奇过mysql是如何存储NULL值,实际上NULL值并没有被真正的存储,而是用一个标记位来标记那一个字段的值为null,这个标记位用二进制表示,0为非null,1为null。而在实际的列数据中,并没有占用空间,(注意,这是Compact格式下,Redundant格式下,char的null值还是会占用空间)。

  • 记录头信息在这里插入图片描述

  • 列数据
    列数据除了保存有用户定义的数据,还包含了两个隐藏列,事务ID列和回滚指针列,如果表没有指定主键,还会创建一个6格字节的RowID作为默认主键。另外,如果创建了视图,还有有视图的事务ID,回滚指针和RowID,所以总共会有6个保留隐藏列。

2.Redundant格式

在这里插入图片描述

null值的存储

可以看到,相比Compact,少了一个NULL值标记位。那么Redundant格式是如何保存null值的

  • 对于varchar类型
    字段长度偏移列表中记录了varchar的长度,也就是0,所以在列数据中,varchar实际页不占用空间
  • 对于char类型
    字段长度偏移列表中记录了char的固定长度,所以并不是0,所以在列数据中,char会实际占用空间。而且,char会占用可能存放的最大空间。
    可以看出,相对于Compact,Redundant存储格式的null值更占用空间。
最大列数

另外值得注意的一点是,在Redundant格式中记录头信息中,有个字段n_fields,记录了列数。
在这里插入图片描述

可以在图中看出,n_fields是一个占用10个bit大小的值,因此,一个表最大列数只能是1023(2^10-1),但是如果你还记得上面Compact说过,实际上还有6个隐藏的列,所以实际上,用户最多只能创建1023-6=1017列。

不过令人存疑的是,Compact格式下并没有n_fields,那么如果表是Compact格式,是否能够创建的列就不受限制呢?于是我尝试创建了一个1018列的Compact格式的表,但是依然提示错误“Too many columns”;可能是为了兼容,InnoDB做了限制。不过一个表这么多列,也不是一个好的数据库表设计。

char的保存格式

另外,从mysql4.1开始,char(2)括号中的数字指的是字符的长度而不是字节的长度,比如“中文”,字节长度为4,字符长度为2,所以一个char(2)的字段是可以存储“中文”这个字符串的。所以实际上,char的存储方式跟varchar的存储方式是一样的,也是变长的。

行溢出数据

一般我们认为,对于text,blob数据,并不会和其他数据存放在同一页,而是单独存放在一个页里面,但是实际上真的是这样吗?
实际上,如果长度小于8089,那么,并不会存放在单独的页里面,而是直接存放在行数据所在的页。即使超出了阈值,也不是全部存放在新的页,而是任然会保留部分数据在行数据所在的页(前768个字节)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值