【MySQL】InnoDB数据存储结构

1、数据页内部结构

第一部分:文件头部+文件尾部

主要包含了对页面之间双向链表的表示、页面校验和、页面最后被修改对应的日志序列位置

第二部分:空闲空间+用户记录+最小最大记录

用户记录:

​ 用户记录中的记录按照指定的行格式一条条摆在该区域,相互之间形成单链表。

第三部分:页目录+页面头部

页目录:

1、页目录分组的个数如何确定?

由InnoDB规定:最小记录所在的分组只能有一条记录,最大记录所在分组的记录条数只能在18之间,剩下的分组中记录的条数在48之间。

2、页目录结构下如何快速查找记录?

1、通过二分法确定该记录所在的槽,并记录该槽所在分组中主键值最小的那条记录。

2、通过记录的next_record属性遍历该槽所在组中的所有记录。

页面头部:

记录了页目录和页面的相关信息

2、InnoDB行格式

sql 复制代码
CREATE TABLE 表名 ROW_FORMAT=行格式
ALTER TABLE 表名 ROW_FORMAT=行格式

2.1、COMPACT行格式

NULL值列表

为什么定义NULL值列表?

​ 定义NULL值列表是因为数据是需要对齐的,如果没有标注出NULL值的位置,在查询数据的时候有可能会出现混乱,记录的格式为:

  • 1、二进制值为1时,代表该列的值为NULL
  • 2、二进制值为0时,代表该列的值不为NULL

​ 在这个过程中会 跳过主键,因为主键不为空。

记录头信息:
字段 大小(bit) 描述
delete_mask 1 该记录是否被删除
min_rec_mask 1 B+树每层非叶子节点的最小节点
record_type 4 当前记录类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
heap_no 13 当前记录在记录堆的位置信息
n_owned 3 当前记录拥有的记录数
next_record 16 下一条记录的相对位置,指向下一条记录的逻辑位置

问题:

1、使用delete_mask标记当前记录是否被删除,被删除的记录为什么还在页中存储呢?

​ 这些被删除的记录之所以不立即从磁盘上移除,是因为移除它们之后其他记录在磁盘上需要重新排列,导致性能消耗。通过将所有打上删除标记的记录组成垃圾链表,之后如果有新纪录插入到表中来时,可以把这些被删除的记录占用的存储空间覆盖掉。

2、heap_no为什么是从2开始的?

​ MySQL自动给每个页里加了两个虚拟记录,一个代表最小记录名,heap_no值为0;一个代表最大记录,heap_no值为1。

2.2、Dynamic和Compressed行格式

​ Dynamic和Compressed将实际数据存放在溢出页中,Compressed行记录格式会将存储在其中的行数据以zlib的算法进行压缩。

行溢出

​ 一个页的大小为16KB,也就是16384字节,而VARCHAR类型的列最多可以存储65535个字节,这样可能会出现一页存放不下一条记录的情况。这就是行溢出。

相关推荐
数据库急诊室_阿哲3 小时前
一次加索引建议的复核记录:从报告到签字
数据库·ai数据库
青瓦梦滋4 小时前
Redis主从复制
服务器·数据库·redis·缓存·bootstrap
慧都小妮子5 小时前
Wyn商业智能国产数据库适配:数据接入、分析缓存与审计日志验证清单
数据库·数据分析·数据可视化·审计日志·商业智能
Joy T5 小时前
Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制
数据库·redis·lua·限流·竞态条件·redis scripting
杨凯凡6 小时前
MySQL 死锁怎么排查?InnoDB 锁等待与 Spring Boot 整事务重试实战
数据库·spring boot·mysql
Aloudata6 小时前
Claude 做数据分析的这两年:一份复盘与发展线索
大数据·数据库·人工智能·数据挖掘·数据分析·dataagent
Decay__6 小时前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构
zhanghaha13146 小时前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#
韩曙亮6 小时前
【错误记录】安卓 adb 调试 5037 端口占用排查 ( adb 的三层结构 | 找出本机占用 5037 的进程 )
android·数据库·adb·安卓·错误记录
瑞雪兆丰年兮7 小时前
JavaWeb-day07-MySQL(DQL&多表设计)
java·开发语言·数据库·sql·mysql·javaweb·web