首页 > 数据库 >MySQL存储引擎-InnoDB行格式

MySQL存储引擎-InnoDB行格式

时间:2024-02-05 19:44:07浏览次数:27  
标签:00 字节 记录 存储 列表 InnoDB MySQL 格式 NULL

MySQL存储引擎-InnoDB行格式

mysql作为一款主流的关系型数据库,是以记录为单位向表中插入数据的。目前为止,Innodb共支持COMPACT、 REDUNDANT、 DYNAMIC、和COMMPRESSED四种行格式。在MySQL5.7及以上版本,默认采用DYNAMIC格式。DYNAMIC与COMPACT格式基本一致,下文中我们会介绍区别。因其他类型日常工作中很少用到,本文作为读书笔记,不再进行介绍。

一、COMPACT行格式

我们首先创建一个示例表,如下:

create table record_format_demo (
  c1 varchar(10),
  c2 varchar(10) not null,
  c3 char(10),
  c4 varchar(10)
) charset = ascii row_format = compact;
insert into record_format_demo values('aaaa','bbb','cc','d');
insert into record_format_demo values('eeee','fff',NULL,NULL);

一条完整的记录被分为记录的额外信息和记录的真实数据两部分。

1.1、记录的额外信息

记录的额外信息分为3部分,分别是变长字段长度列表, NULL值列表,和记录头信息。

变长列表指的是varchar等不固定的长度类型,变长字段真实数据占用的字节数存储在记录的开头位置。形成一个变长字段长度列表,变长字段的真实数据所占用的字节数按照列的顺序逆序排放。例如示例表中的第一行数据。该示例表变长字段为c1、c2、c4列。因为我们使用的是ascii字符集,所以每个字符占用1字节。 因此:第一行数据的变长字段长度列表用十六进制表示为 01 03 04。 这个示例中的长度都可以用1字节表示,那如果变成字段的真实内容占用字节数很多,可能就用2字节来表示。InnoDB的规则是:如果变成字段允许存储的最大字节数小于255就用1个字节表示,如果大于255并且真实数据占用的字节数超过127字节就使用2字节来表示,不超过177就使用一个字节表示。 我们再看示例表的第二行,因为c4列为null。变成字段长度列表不存储NULL列的内容长度,因此第二行的变长列表为 03 04。

NULL值列表,在COMPACT中,把一条记录中为NULL的列统一管理,存储到NULL值列中。处理过程如下:首先统计允许存储NULL的列有哪些,例如示例表中的c1、c3、c4。如果表的所有列都不会NULL, 那NULL值列表就不存在了。如果有NULL值,就按照允许存储NULL的列对应一个二进制位,二进制为按照列的顺序逆序排列。二进制位为1时代表该列的值为NULL,为0时代表该列不为NULL。另外MySQL的NULL值列表必须用整数个字节表示,不足的在最高位补0。根据这个规则我们可以推算示例表中第一行数据的NULL值列表为 0 0 0 0 0 0 0 0 。第二行的NULL值列列表为 0 0 0 0 0 1 1 0。 转换为十六进制则为 00 和 06。

记录头信息,记录头信息固定5个字节,用于描述记录的一些属性。5个字节即40位,不同位代表不用的函数。二进制位代表的含义如下所示:

1、预留位  1位

2、预留位  1位

3、delete_flag  1位 标记是否删除

4、n_owned  4位  一个页面的记录会被分为若干组。每个组中有一个记录是大哥,其余为小弟。大哥的n_owned代表改组的记录条数,小弟的n_owned为0

5、heap_no  13位  表示当前记录在页面堆的相对位置

6、record_no  3位   表示记录类型。 0表示普通记录,1表示非叶结点记录,2表示Infimum记录, 3表示Supermum记录

7、next_record 16位  表示下一条记录的相对位置

1.2、记录的真实数据

MySQL的除了我们插入的真实数据之外,还会插入一些隐藏列。包括 rowid (6字节,在没有主键和非空唯一索引会创建)、trx_id (6字节,事务id)、roll_pointer (7字节,回滚指针)。根据以上我们的分析,我们通过hexdump指令来分析一下示例表的数据文件。结果如下:这里只截了一部分,即包含行数据的部分。

因此我们可以得到前两行的行记录为: 

说明 变长字段 NULL值列表 记录头信息 row_id trx_id roll_pointer c1列 c2列 c3列 c4列
第一行 01 03 04  00 00 00 10 00  2d 00 00 03 67 c5 78   00 00 13 82 3e 9e  a6 00 00 c0 2c 01 10   61 61 61 61   62 62 62 63 63 20 20 20 20 20 20 20 20   64
第二行  03 04  06 00 00 18 ff c2  00 00  03 67 c5 79 00 00 13 82  3e 9f a7 00 00 01 ca 01 10   65 65 65 65  66 66 66    

1.3、char列存储格式

在上述示例表中,我们采用的ascii字符集属于定长字符集即1个字节。如果使用变长字符集如utf8,utf8表示一个字符需要1~3个字节。针对变长字符集,虽然c3列的类型为char(10)。这一列的值占用的字节数也会被存储到变长字段长度列表中。执行如下sql修改:

alter table record_format_demo modify column c3 char(10) character set utf8;

那该列也会被加入变长列表:如图所示: 第一行的变长字段的长度列表变为了 01 0a 03 04

 1.4、溢出列

我们创建一个溢出列的测试表,如下所示:

create table off_page_demo(c varchar(65532)) charset=ascii row_format=compact;
insert into off_page_demo values(repeat('a', 65532));

上述表中,这个字符串大小为65532字节。我们知道MySQL一个数据页才16K,即16382字节,很显然1个数据页中存不了一条记录。 在COMPACT格式中:对于占用存储空间非常多的列,在记录的真实数据处只存储一部分数据,而把剩余的数据分散存储在其他页中。然后在记录真实数据处用20字节存储指向这些页的地址。(这20字节还包括分散在其他页中的数据所占的字节数)。 对于COMPACT格式,如果某些数据很多,则在本记录的真实数据处只存放768个字节和指向其他页的地址。 存储剩余数据的页叫做溢出页。

MySQL规定一个页至少存储2条记录。对于溢出页没有这个规定

二、其他格式

另外两个行格式,DYNAMIC格式和COMPRESSED格式。这另个行格式和COMPACT格式很像,只不过在处理溢出列时有些分歧。他们不会在记录真实数据处存储前768字节,而是把该列的所有真实数据全部存放到溢出页中。只在记录真实数据处存储20字节大小的指向溢出页的地址,COMPRESSED会采用压缩算法对页面进行压缩,基本用不到,就不再介绍了。

 

标签:00,字节,记录,存储,列表,InnoDB,MySQL,格式,NULL
From: https://www.cnblogs.com/jkin/p/18008417

相关文章

  • PowerDesigner 导出mysql
    首先打开powerdesigner,可以通过文件打开一个项目或者直接双击项目通过powerdesigner进行打开。修改导出数据库类型。点击工具栏上的“Database”,选择“ChangeCurrentDBMS”进行修改导出脚本类型,可以选择mysql、sqlserver/oracle、db2等主流的数据库。在DBMS中点击下拉菜单,选择......
  • MySQL常用图形管理工具
    MySQL图形化管理工具极大地方便了数据库的操作与管理,常用的图形化管理工具有MySQLWorkbench、phpMyAdmin、Navicat、MySQLDumper、SQLyog、MySQLODBCConnector。其中,phpMyAdmin和Navicat提供中文操作界面;MySQLWorkbench、MySQLODBCConnector、MySQLDumper为英文界面。下......
  • MySql聚集索引和非聚集索引的区别
    MySql中的聚集索引和非聚集索引主要体现在以下几个方面:1.存储方式:聚集索引的叶子节点存储的是整行数据,非聚集索引叶子节点存储的是键值和整行的标识。2.索引结构:聚集索引的索引结构于数据表的物理结构相同,非聚集索引的索引结构与数据表的物理结构不同。   在数......
  • 踩坑了,MySQL数据库生成大量奇怪的大文件
    作者:田逸(formyz)一大早就收到某个数据库服务器磁盘满的报警信息,其中数据盘使用率超过90%,如下图所示。这是一台刚上线不久的MySQL从库服务器,数据盘的总容量是300G。先登录系统,查看主从同步是否正常,幸运的是主从同步正常;再看看磁盘空间的使用情况,执行的命令及输出如下。df-h[root@MyS......
  • mysql模糊查询如何能用到索引?
    mysql模糊查询%我就不多说了。想要%不在左边也能用到索引,可以选择加全文索引假设我的表是wa_log记录日志的,url是访问的路径,想要查询url路径中包含admin的数据ALTERTABLEwa_logADDFULLTEXT(url);EXPLAINSELECT*FROMwa_logWHEREMATCH(url)AGAINST('admin'INBOOLEAN......
  • mysql如何实现左连接、右连接
    学生表 students学生ID学生姓名1张三2李四3王五4小六5小七成绩表 grades学生ID课程学生成绩1数学862语文793数学914英语881、查询所有学生的id、姓名、成绩用左连接可以实现:SELECTstudents.学生ID,students.学生姓名,grades.成绩FROMstudentsLEFTJOINgradesONstudents.......
  • mysql-自定义函数
    0、结构delimiter$$--修改语句结束符,mysql默认的结束符是分号,为了在函数体中避免遇到分号就结束,重新定义结束符createfunction函数名(形参)returns返回值类型begin//函数体return返回值数据;end$$delimiter;--将语句结束符修改回来1、变......
  • centos系统安装mysql并开放端口外部使用
    查看安装包:https://dev.mysql.com/downloads/repo/yum/下载MySQL源:wgethttp://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm安装MySql源yum-yinstallmysql57-community-release-el7-11.noarch.rpm查看一下安装效果yumrepolistenabled|grepmysq......
  • mysql问题记录
    Mac下brew安装mysqlsudomysql.serverstart报错StartingMySQL.Loggingto'/usr/local/var/mysql/192.168.0.102.err'...ERROR!TheserverquitwithoutupdatingPIDfile(/usr/local/var/mysql/192.168.0.102.pid).解决办法sudochown-Rmysql/usr/local/var......
  • 非空处理 Java非空判断 非空处理及mysql数据库字段的not null
    1.mysql##去掉非空,如果非空又没有默认值,这样程序在添加数据的时候i,如果没有设置值就会报错。该操作很危险。##ALTERTABLE`order_test`ADDCOLUMN`test_card_name`NOTNULLVARCHAR(200)COMMENT'卡名称';##修改允许为空..ALTERTABLE`order_test`MODIFYCOLUMN`test......