MySQL存储引擎InnoDB行格式

249次阅读
没有评论

共计 3255 个字符,预计需要花费 9 分钟才能阅读完成。

InnoDB 规划了 26 种行格式,分别对应 26 种动物,首字母由 A 至 Z:Antelope, Barracuda, Cheetah, Dragon, Elk, Fox, Gazelle, Hornet, Impala, Jaguar, Kangaroo, Leopard, Moose, Nautilus, Ocelot, Porpoise, Quail, Rabbit, Shark, Tiger, Urchin, Viper, Whale, Xenops, Yak, Zebra。

目前 InnoDB 支持的行格式只有 Antelope, Barracuda。而 Antelope 又具体细分为 Redundant 和 Compact,Barracuda 也具体细分为 Dynamic 和 Compressed。

可以在创建或修改表的语句中指定行格式:

CREATE TABLE 表名 (列的信息) ROW_FORMAT= 行格式名称
ALTER TABLE 表名 ROW_FORMAT= 行格式名称

Compact

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

记录额外信息

记录额外信息是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为 3 类,分别是 变长字段长度列表 NULL 值列表记录头信息

变长字段长度列表

在 Compact 行格式中,把所有变长字段的真实数据占用字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,各变长字段数据占用字节数(十六进制表示)按照列的顺序 逆序 存放。

用 1 个还是 2 个字节来表示真实数据占用字节数,InnoDB 有它的一套规则:

  1. 假设某个字符集中表示一个字符最多需要使用的字节数为 W,也就是使用SHOW CHARSET 语句结果中的 Maxlen 列,比方说 utf8 字符集中 W 就是 3gbk 字符集中 W 就是 2ascii 字符集中 W 就是1
  2. 对于变长类型 VARCHAR(M) 来说,这种类型表示能存储最多 M 个字符(注意是字符不是字节),所以这个类型能表示的字符串最多占用的字节数就是M × W
  3. 假设实际存储的字符串占用字节数是L

所以确定使用 1 个字节还是 2 个字节表示真正字符串占用字节数规则就是这样:

  • 如果M×W <= 255,那么使用 1 个字节来表示真正字符串占用字节数
  • 如果M×W > 255,则分为两种情况:

    • 如果L <= 127,则用 1 个字节来表示真正字符串占用字节数
    • 如果L > 127,则用 2 个字节来表示真正字符串占用字节数

InnoDB 在读记录的变长字段长度列表时会先查看表结构,如果某个变长字段允许存储的最大字节数大于 255 时,该怎么区分它正在读的某个字节是一个单独的字段长度还是半个字段长度呢?InnoDB 使用该字节的第一个二进制位作为标志位:如果该字节的第一个位为 0,那该字节就是一个单独的字段长度(使用一个字节表示不大于 127 的二进制的第一个位都为 0),如果该字节的第一个位为 1,那该字节就是半个字段长度。

需要注意的是,变长字段长度列表中只存储值为 非 NULL的列内容占用长度,值为 NULL 的列长度是不储存的。

对于 CHAR(M) 类型的列来说,当列采用的是定长字符集时,该列占用字节数不会被加到变长字段长度列表,而如果采用变长字符集时,该列占用字节数也会被加到变长字段长度列表。

最后,并不是所有记录都有这个变长字段长度列表部分,比方说表中所有列都不是变长数据类型,这一部分就不需要有。

NULL 值列表

如果把 NULL 值都放到 记录真实数据 中存储会很占地方,所以 Compact 行格式把这些值为 NULL 的列统一管理起来,存储到 NULL 值列表中,它的处理过程是这样的:

  1. 首先统计表中允许存储 NULL 的列有哪些
  2. 如果表中没有允许存储 NULL 值的列,则 NULL 值列表也不存在,否则将每个允许存储 NULL 的列对应一个二进制位,二进制位按照列的顺序 逆序 排列,二进制位表示的意义:值为 1 时,代表该列的值为 NULL;值为0 时,代表该列的值不为NULL
  3. MySQL 规定 NULL 值列表必须用整数个字节的位表示,如果使用的二进制位个数不是整数个字节,则在字节的高位补0。如果一个表中有 9 列允许为 NULL,那这个 NULL 值列表部分就需要 2 个字节来表示

记录头信息

由固定的 5 个字节组成,即 40 个二进制位,不同的位代表不同的意思。这些二进制位代表的详细信息如下:

名称 大小(bit) 描述
预留位 1 1 没有使用
预留位 2 1 没有使用
delete_mask 1 标记该记录是否被删除
min_rec_mask 1 B+ 树每层非叶子节点中的最小记录都会添加该标记
n_owned 4 表示当前记录拥有的记录数
heap_no 13 表示当前记录在记录堆的位置信息
record_type 3 表示当前记录的类型,0 表示普通记录,1 表示 B + 树非叶子节点记录,2 表示最小记录,3 表示最大记录
next_record 16 表示下一条记录的相对位置

delete_mask这个属性标记当前记录是否被删除,值为 0 代表记录并没有被删除,为 1 代表记录被删除掉了。这些被删除的记录之所以不立即从磁盘上移除,是因为移除它们之后把其他的记录在磁盘上重新排列需要性能消耗,所以只是打一个删除标记而已,所有被删除掉的记录都会组成一个所谓的 垃圾链表 ,在这个链表中的记录占用的空间称之为所谓的 可重用空间,之后如果有新记录插入到表中的话,可能会把这些被删除记录占用的存储空间覆盖掉。

heap_no这个属性表示当前记录在记录堆的位置信息,InnoDB 会自动给每个页里边儿加了两个记录,由于这两个记录并不是我们自己插入的,所以有时候也称为伪记录或者虚拟记录。这两个伪记录一个代表最小记录(heap_no 值为 0),一个代表最大记录(heap_no 值为 1)。

next_record非常重要,它表示从当前记录真实数据到下一条记录真实数据的地址偏移量。比方说第一条记录的 next_record 值为 32,意味着从第一条记录真实数据的地址处向后找 32 个字节便是下一条记录真实数据。

记录真实数据

记录真实数据除了自己定义的列数据外,MySQL 会为每个记录默认添加一些列(也称为隐藏列),具体如下:

列名 是否必须 占用空间 描述
row_id 6 字节 行 ID,唯一标识一条记录
transaction_id 6 字节 事务 ID
roll_pointer 7 字节 回滚指针

实际上这几个列的真正名称是:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR。

需要注意的是,变⻓字符集的 CHAR(M)类型列要求⾄少占⽤ M 个字节,⽽ VARCHAR(M)却没有这个要求。

Redundant

该行格式是 MySQL 5.0 之前使用的一种行格式,也就是说它已经非常老了,这里就不介绍了。

行溢出

对于 VARCHAR(M)类型的列最多可以占用 65535 个字节,其实这个 65535 除了列本身的数据之外,还包括一些其他数据(storage overhead)。如果该 VARCHAR 类型列没有 NOT NULL 属性,那最多只能存储 65532 个字节数据,因为真实数据长度可能占用 2 个字节,NULL 值标识需要占用 1 个字节。

在 Compact 和 Reduntant 行格式中,对于占用存储空间非常大的列,在记录真实数据处只会存储该列的一部分数据,剩余数据分散存储在几个其他页中,然后记录真实数据处用 20 个字节存储指向这些页的地址,从而可以找到剩余数据所在的页。这个过程也叫做行溢出,存储剩余数据所在页也被称为溢出页。

发生行溢出的临界点是什么呢?也就是说在列存储多少字节数据时会发生 行溢出?其实,不用关注这个临界点是什么,只要知道如果一个行中存储了很大的数据时,可能发生行溢出的现象就行了。

Dynamic 和 Compressed 行格式

MySQL 5.7 默认行格式就是 Dynamic,这俩行格式和 Compact 行格式挺像,只不过在处理行溢出数据时有点儿分歧,它们不会在记录真实数据处存储字段真实数据的前 768 个字节,而是把所有字节都存储到其他页面中,只在记录真实数据处存储其他页面的地址。

Compressed 和 Dynamic 不同的一点是,Compressed 行格式会采用压缩算法对页面进行压缩,以节省空间。

正文完
 0
阿伯手记
版权声明:本站原创文章,由 阿伯手记 于2024-01-29发表,共计3255字。
转载说明:本站原创内容,除特殊说明外,均基于 CC BY-NC-SA 4.0 协议发布,转载须注明出处与链接。
评论(没有评论)
验证码

阿伯手记

阿伯手记
阿伯手记
喜欢编程,头发渐稀;成长路上,宝藏满地
文章数
766
评论数
204
阅读量
446903
今日一言
-「
热门文章
职场救急!AI请假话术生成器:1秒定制高通过率理由

职场救急!AI请假话术生成器:1秒定制高通过率理由

超级借口 不好开口?借口交给我!智能生成工作请假、上学请假、饭局爽约、约会拒绝、邀约推辞、万能借口等各种借口理...
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
巴别英语:用美剧和TED演讲轻松提升英语听力与口语

巴别英语:用美剧和TED演讲轻松提升英语听力与口语

还在为枯燥的英语学习而烦恼吗?巴别英语通过创新的美剧学习模式,让英语学习变得生动有趣。平台提供海量美剧和 TE...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
TVAPP:开源电视盒子资源库,一键打造家庭影院

TVAPP:开源电视盒子资源库,一键打造家庭影院

导语 TVAPP 是一个专为 Android TV 电视盒子用户打造的开源影音资源库,集成了影视、直播、游戏等...
2025年12月 每日精选

2025年12月 每日精选

关于每日精选栏目 发现一些不错的资源,点击 这里 快速投稿。 12 月 26 日 .ax 顶级域 目前全球唯一...
最新评论
15220202929 15220202929 怎么用
八对 八对 麻烦大佬更新下【堆新】的友链站名:八对星星描述:极目星视穹苍无界•足履行者大地有疆链接:https://8dui.com图标:https://cf.8dui.com/logo.webp横标:https://cf.8dui.com/logo-w.webp订阅:https://8dui.com/rss.xml
三毛笔记 三毛笔记 已添加
DUINEW DUINEW 已添加贵站,期待贵站友链~博客名称:堆新博客地址:https://duinew.com/博客描述:堆新堆新,引力向新!——堆新(DUINEW)博客头像:https://d.duinew.com/logo.webp横版头像:https://d.duinew.com/logo-w.webp博客订阅:https://duinew.com/rss.xml
hedp hedp 没看懂
bingo bingo 直接生成就可以啦,也可以添加一些选项
满心 满心 申请更新下友联信息,原名:满心记,现名:周天记原域名:qq.mba,现域名:zhoutian.com描述:我在人间混日子
开业吉日 开业吉日 没看明白这个怎么用
开业吉日 开业吉日 beddystories 这个网站太赞了,收藏
热评文章
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
清华大学官方免费DeepSeek教程

清华大学官方免费DeepSeek教程

AI 领域近期最引人注目的焦点当属 DeepSeek,这款由中国创新企业深度求索研发的人工智能工具,正以开放源...
Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 是一款基于 Fastify、Vercel 和 Supabase 构建的 URL 缩短服务...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 是一个致力于为儿童提供优质睡前故事的在线平台,用户可以在这里找到来自世界各地的经典故...
DrawLink:一键生成链接视觉卡片,提升分享点击率

DrawLink:一键生成链接视觉卡片,提升分享点击率

小贴士 :此站或已变迁,但探索不止步。我们已为您备好「类似网站」精选合集,相信其中的发现同样能为您带来惊喜。