InnoDB 行超长时怎么选择溢出字段?

InnoDB 索引页的大小默认为 16K,然而,varchar、text、blob 类型的单个字段内容长度就有可能超过 16K,这种情况下,整个索引页都存不下一个字段的内容了。

解决这个问题的办法,是找到那些内容比较长的字段作为​​溢出字段​​,把它们的内容存放到溢出页中,减少留在索引页记录中的内容。

接下来,我们来聊聊 InnoDB 选择溢出字段的逻辑。

本文内容基于 MySQL 8.0.29 源码。

正文

进入正题之前,大家可以思考一个问题:一个表中每条记录的溢出字段都是一样的吗?

1、建表时的限制

单从字段数量看,MySQL 的 server 层限制一个表最多只能创建 1024 个字段。

InnoDB 则限制最多只能创建 1023 个字段,但是,如果我们创建表时,真要创建 1023 个字段,会很荣幸的收到这个错误:1117 – Too many columns。

因为 InnoDB 会往表中增加 2 ~ 3 个隐藏字段:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR。

只有表中没有主键,并且在建表时也没有创建所有字段都不允许为 NULL​ 的唯一索引时,才会增加 DB_ROW_ID 字段。

创建表时,能定义 1023 – 3 = 1020 个字段吗?

依然不能,因为崩溃恢复过程中,解析 Redo 日志时,REDUNDANT​ 记录还会往表的内存对象(dict_table_t)中加入 3 个字段。

从以上介绍可知,InnoDB 需要保留 6 个字段自用,所以,我们建表时,最多能创建的字段数量是:1023 – 3 * 2 = 1017。

表中实际能创建多少个字段,除了受限于 server 层和存储引擎的字段数量限制,还会受到字段长度的限制。

创建表时,InnoDB 会问自己一个问题:

如果我放过这条 DDL 语句,让它建表成功,以后对这个表进行插入、更新操作时,有没有可能因为记录超长导致操作失败?

要回答这个问题,总不能凭空想象,随心而动吧?

所以,得有一个规则,要按规则办事,规则是这样的:

假定有资格被选择成为溢出字段的那些字段,都已经被当作溢出字段了,它们的字段内容都部分或全部存放到溢出页中了。

溢出字段内容是部分还是全部存放到溢出页,这取决于记录的格式。

REDUNDANT、COMPACT 记录只会把溢出字段的部分内容存放到溢出页。

DYNAMIC、COMPRESSED 记录会把溢出字段的全部内容存放到溢出页。

在这个规则之下,再来计算留在索引页中的记录内容长度,看看是不是还会超长?

如果还会超长,InnoDB 是不会放过这条 DDL 语句的,这时,建表就会失败,并且报如下错误:

1118-Rowsizetoolarge (>8126).
ChangingsomecolumnstoTEXTorBLOBmayhelp.
Incurrentrowformat, BLOBprefixof0bytesisstoredinline.

为啥判断超长的条件是大于 8126 字节呢?先别急,后面会有介绍。

如果不会超长,自然就会建表成功了。

2、索引页长什么样?

InnoDB 的索引页,不管是 B+ 树的非叶子结点,还是叶子结点,初始化完成之后,未插入记录之前,都包含以下几个部分:

  • 38 字节的 File Header
  • 56 字节的索引页头信息
  • 13 字节的 Infimum 记录
  • 13 字节的 Supremum 记录
  • 2 字节的 Supremum Slot
  • 2 字节的 Infimum Slot
  • 8 字节的 File Trailer

总共占用 132 字节,如下图所示:

3、怎么判断行超长了?

通过上一小节,我们知道一个索引页初始化完成之后,会占用 132 字节的空间。

索引页默认大小为 16K,初始化之后,索引页中剩余空间为:16 * 1024 – 132 = 16252 字节。

InnoDB 规定​:一个索引页中最少要存放 2​ 条记录。所以,索引页中一条记录的最大长度就是:16252 / 2 = 8126 字节。

插入或者更新记录时,如果插入记录的长度,或者更新之后记录的长度大于 8126 字节,就会选择记录中的部分字段作为溢出字段。

一条记录的长度为下几个部分的长度之和:

  • 字段 NULL 标记区域​,标记每个字段内容是否为 NULL,如果表中所有字段都定义为NOT NULL​,记录中没有此区域。
  • 字段内容长度区域​,存储每个变长​字段的内容长度,如果表中所有字段都不是​变长字段,记录中没有此区域。
  • 记录的头信息,REDUNDANT 格式:6 字节;COMPACT、DYNAMIC、COMPRESSED 格式:5 字节。
  • 用户字段内容。
  • DB_ROW_ID​,6 字节,创建表时,表中既没有主键,也没有创建所有字段都定义为 NOT NULL 的唯一索引时,InnoDB 才会添加这个列,作为表的主键。
  • DB_TRX_ID,8 字节,最后修改记录的事务 ID。
  • DB_ROLL_PTR,7 字节,指向上一个事务产生的 undo 日志。

4、选择溢出字段的逻辑

选择溢出字段环节可能会进行一轮或多轮循环,每轮循环从表中选择一个​字段作为溢出字段,直到留在索引页中的记录长度小于等于 8126 字节,选择溢出字段环节也就结束了。

选择溢出字段时,有一些字段是会被排除在外的,命中​以下规则的字段都不会被选为溢出字段:

  • 主键字段。
  • 固定长度字段(char、binary 字段除外)。
  • 内容为 NULL 的字段。
  • REDUNDANT、COMPACT 记录,字段内容长度<= 788 字节。
  • DYNAMIC、COMPRESSED 记录,字段内容长度<= 40 字节​,且字段类型是 BLOB、GEOMETRY、VAR_POINT。
  • DYNAMIC、COMPRESSED 记录,字段内容长度<= 255 字节​,且字段类型不是 BLOB、GEOMETRY、VAR_POINT。

没有命中以上规则的字段,都有资格被选为溢出字段。

每轮循环都会遍历表中的所有字段,并根据以上规则,从有资格被选为溢出字段的那些字段中,找到​​内容最长​​的字段,就是溢出字段了。

5、页地址

字段被选为溢出字段之后,该字段的部分或全部内容会存放到溢出页,然后,索引页记录中,该字段的末尾​,会有一个 20 字节​的区域,保存着溢出页地址。

20 字节的溢出页地址由以下 4 个部分构成:

  • 表空间 ID,4 字节,溢出页所在表空间 ID。
  • 页号,4 字节,第 1 个溢出页的页号。一个溢出页存不下字段的溢出内容时,会有多个溢出页,组成溢出页链表。
  • 字段内容 Offset​,4 字节,第 1 个溢出页中,字段内容在页中的 Offset。根据是否启用了压缩页,字段内容在溢出页中的 Offset 会不一样,所以需要记下来。
  • 溢出页内容长度​,当前字段存放到溢出页中的内容长度,8 字节,实际只使用了最后4 字节来存储溢出页的内容长度之和,如下图所示:

溢出字段留在索引页记录中的内容根据记录格式的不同而不同:

REDUNDANT、COMPACT 记录​,溢出字段在索引页记录中的长度为 788 字节,由以下两部分组成:

  • 768 字节的字段内容。
  • 20 字节的溢出页地址。

溢出字段中 768 字节之后的内容,会存放到溢出页中。

DYNAMIC、COMPRESSED 记录,溢出字段的全部内容都会存放到溢出页中,索引页记录中只保存 20 字节的溢出页地址。

6、回答文章开头的问题

经过前面的介绍,相信大家对于本文开头的那个问题已经有了答案,回到问题:

问:一个表中每条记录的溢出字段都是一样的吗?

答​:每条记录的溢出字段,可能一样,也可能不一样,记录中哪些字段会成为溢出字段,取决于每条记录中,所有有资格被选为溢出字段的内容长度。

7、总结

一条记录中,所有字段内容长度之和超过 8126 字节时,就会有部分字段被选择成为溢出字段。

选择溢出字段可能会进行多轮循环​,每轮循环都会从有资格被选为溢出字段的那些字段中,选择内容最长​的字段作为溢出字段,直到留在索引页中的记录长度小于等于 8126 字节。

REDUNDANT、COMPACT 记录,溢出字段内容的前 768 字节存放在索引页记录中,剩余内容存放到溢出页。

DYNAMIC、COMPRESSED 记录,溢出字段的全部内容都存放到溢出页。

本文转载自微信公众号「一树一溪」,可以通过以下二维码关注。转载本文请联系一树一溪公众号。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/299092.html<

(0)
运维的头像运维
上一篇2025-05-23 06:03
下一篇 2025-05-23 06:04

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注