当前位置: 首页 > news >正文

从零起步学习MySQL || 第六章:MySQL数据库中的一条数据是如何存储的?(结合源码深度解析)

一、InnoDB 的行格式(Row Format)

InnoDB 是 MySQL 默认的存储引擎。它在物理层面上存储表数据时,每一行(row)都按一定格式组织在 数据页(data page) 中。

1. InnoDB 支持的行格式

InnoDB 一共有四种行格式:

行格式简介
REDUNDANT最早的行格式(MySQL 5.0 之前),已不推荐使用。
COMPACTMySQL 5.0 起默认格式(高效节省空间)。
DYNAMICMySQL 5.7 起常用,支持大字段页外存储。
COMPRESSED与 DYNAMIC 类似,但数据页还会压缩以节省空间。

👉 通常我们使用 COMPACTDYNAMIC
配置方式示例:

 

CREATE TABLE t( id INT, name VARCHAR(255) ) ROW_FORMAT=COMPACT;


二、COMPACT 行格式的结构(重点)

每一条记录的存储结构如下(从前往后):

 

| 变长字段长度列表 | NULL标志位 | 记录头信息 | 实际数据(列数据) |

我们一部分一部分看:


1️⃣ 变长字段长度列表 (Variable-length field length list)

  • 对于可变长类型(如 VARCHAR, VARBINARY, TEXT),InnoDB 在行首存储这些字段的长度信息。

  • 顺序是逆序存放(最后一个可变长列的长度在最前面)。

  • 每个字段占 1 或 2 个字节:

    • 若字段最大长度 ≤ 255,则用 1 字节;

    • 否则用 2 字节。

举例:

 

CREATE TABLE user ( id INT, name VARCHAR(20), email VARCHAR(255) ) ROW_FORMAT=COMPACT;

则一条记录的行首会先存储:

 

email长度(2字节) | name长度(1字节)


2️⃣ NULL 标志位 (NULL bitmap)

  • 若列允许为 NULL,InnoDB 会用位图存储每个字段是否为 NULL。

  • 每 8 个列占用 1 个字节。

  • 若列不允许为 NULL,则不出现在位图中。

例如有 10 个列,其中 6 个允许为 NULL,则 NULL 标志位占:

 

ceil(6 / 8) = 1 字节。


3️⃣ 记录头信息(Record Header)

每条记录都有一个“头部信息”用于链表管理和事务控制,占 5字节

字段长度作用
delete_flag1 bit记录是否被删除(0=未删,1=已删)
min_rec_flag1 bitB+树叶子页中最小记录标志
n_owned4 bit当前记录拥有的记录数(分组管理)
heap_no13 bit记录在页中的位置编号
record_type3 bit记录类型(普通/最小/最大等)
next_record16 bit下一条记录的偏移量

4️⃣ 实际列数据(User Data)

这一部分是真正存放你的列数据的地方。

  • 固定长度列(INT、CHAR等)直接按顺序存。

  • 可变长度列的长度由前面的“变长字段长度列表”指定。

  • NULL 值不会真正存储数据,只在 NULL 标志位体现。


三、记录的额外信息与真实数据

总结一下:

类型含义作用
额外信息变长字段长度列表、NULL 标志位、记录头信息用于描述数据、链表管理、页组织
真实数据用户定义的列值(包括主键、普通列等)实际的业务数据

在 InnoDB 页中,一行记录不仅包含你的列数据,还附带了这些额外的元数据,这使得 InnoDB 能实现事务、索引、MVCC 等高级特性。


四、VARCHAR(n) 中的 n 最大取值是多少?

这个问题很多人容易搞混。

  • VARCHAR(n) 中的 n 表示字符数,而不是字节数。

  • 对于 utf8mb4 编码,一个字符最多占 4 字节

  • 单行最大字节限制65535 字节

因此:

一行所有列(包括额外信息)加起来不能超过 65535 字节。

粗略估算:

  • 若使用 utf8mb4VARCHAR(n) 最大大约是 65535 / 4 = 16383 字符。

  • 实际可取更少,因为还有行头和其他列占空间。


五、行溢出(Row Overflow)与 MySQL 的处理机制

1️⃣ 概念

当行太大(如 TEXT、BLOB、或 VARCHAR 非常长),无法全部存进数据页(一个页大小通常 16KB = 16384 字节)时,就会发生行溢出(Row Overflow)

2️⃣ 处理机制

取决于行格式:

行格式溢出存储方式
COMPACT把大字段的前 768 字节存在页内,其余部分存到溢出页(overflow page),页内只保存一个 20 字节的指针指向溢出页。
DYNAMIC整个大字段都存放在溢出页中,页内只保存 20 字节指针。
COMPRESSED类似 DYNAMIC,但数据页和溢出页会压缩存储。

3️⃣ 读取流程

读取溢出字段时,InnoDB:

  1. 先在主记录中找到溢出页指针;

  2. 再去溢出页中加载完整数据。


六、总结图示(COMPACT 行格式)

 

+--------------------------------------------------------------+ | 变长字段长度列表 | NULL标志位 | 记录头信息 | 实际列数据 | | (逆序存放) | (是否为NULL) | (管理信息) | (用户真实数据) | +--------------------------------------------------------------+

示意:

 

| name_len | email_len | null_bits | header | id | name | email |


✅ 总结要点复习

内容关键点
行格式REDUNDANT / COMPACT / DYNAMIC / COMPRESSED
COMPACT结构[变长字段长度列表][NULL标志位][记录头][数据]
记录额外信息长度列表、NULL位图、头信息(5字节)
VARCHAR(n)最大n 最大约 16383(utf8mb4时),受65535字节限制
行溢出超出页大小时,大字段移至溢出页,页内保存指针
不同行格式溢出差异COMPACT 存前768字节,DYNAMIC 全部移出页内
http://www.dtcms.com/a/511983.html

相关文章:

  • 微信小程序页面配置,基本语法,页面切换,tabbar全局配置
  • 数据结构 07
  • 18.基本的ACL
  • 网站后台编程语言创业中文网站模板
  • 从“刘易斯拐点”到“骑手拐点”,即时零售3.0时代还有多远?
  • 有没有一种app类似网站建设开发定制软件开发
  • 沈阳网站建设建设公司普洱网站建设
  • 蓝桥杯题库——部分简单题题解(Java)
  • 新民电商网站建设程序wordpress淘宝发货插件
  • 多服务隔离部署jenkins自动化脚本:从构建到上线的全流程保障
  • React JSX完全指南
  • CSS进阶 | 不用一行JS!用纯CSS打造会动的现代化单页应用(3D翻转卡片)
  • 云栖重磅|瑶池数据库:从云原生数据底座向“AI就绪”的多模态数据底座演进
  • LeetCode 410.分割数组的最大值
  • python批量读取word表格写入excel固定位置
  • 区块链知识总结
  • 开关电源三种拓扑资料整理
  • xss-labs pass-07
  • ES安装和简单讲解
  • Microtest的整套承包系统(turnkey system)目标电源设备特性
  • 程序员学习大模型必备:2025年“人工智能+“行业标杆案例荟萃(附下载)
  • 山西做网站的公司有哪些网站开发做前端还是后端
  • Ubuntu部署redis
  • 国内高端医疗网站建设网站搜索引擎优化诊断
  • 一次完整的 HTTP 请求经历什么步骤?
  • 清理与重装Docker的完整步骤
  • 一个浏览器多人用?Docker+Neko+cpolar实现跨网共享
  • 石灰土做击实检测网站怎么填教育培训网站源码 模板 php培训机构网站源码培训学校网站源码
  • Rust 与 Python:语法对比全景指南
  • 使用vgpu_unlock在ubuntu 22.04上解锁GTX1060 (by quqi99)