mysql数据是以行的形式存储在数据页中,行与行之间形成一个长的链表。
一行的数据除了insert into xxx values ();插入的数据外还存储了其他的数据信息,但是在执行client连接数据库查询数据时不会显示。
mysql行的格式有Compact,Redundant,Dynamic,Compressed四种,mysql5.5以上的默认compact格式,
查看系统的row_format格式
MariaDB [(none)]> show variables like 'innodb_%format';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| innodb_file_format | Antelope |
+--------------------+----------+
创建表的时候可以指定 row_format=compact
行数据存储compact格式

一、变长字段长度列表
几个点了解一下:
何谓变长?就是不定长。不定长从两个点理解: 字符集与属性类型
变长类型示例:
varchar、varbinary、text、blob这些变长列的实际占用字节数以
逆序方式存储在变长字段长度列表中逆序就是: 根据表中字段前后顺序顺序反过来把字段的内容存储在该字段中
允许的最大字节超过255且实际存储超过127字节, 使用两个字节存储其长度, 否则使用一个字节.(看到有多节省了吗...)
变长列不为
null时,InnoDB才会存储其字节长度如果没有变长列或变长列都为null,则当前记录
没有此部分第一个字节的第一位是标志位,表示是否双字节表示.(有点像
gbk哈)
二、NULL值列表
同样几个点了解一下:
主键列、
not null修饰的列不在此范围内如果没有可以省略此部分。(即除了主键列全是
not null修饰)一个列一个二进制位,1表示
null同样
逆序存放此部分由整数个字节组成, 不足地方高位补0
三、记录头信息

Compact行格式下记录头各部分示意图(来源网络)
| 名称 | 大小(单位: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
被删除的记录值为1, 正常记录为0
delete语句后的记录不会被立刻删除,而是将这条记录的delete_mask置1, 称为delete mask操作,与真正的直接删除要区分开(update不更新主键且不能就地更新时直接删除,也就是改完delete_mask后直接加入到垃圾链表中),这种操作是因为MySQL还有一个东东叫MVCC,后面会讲。这个属性还涉及垃圾链表、重用空间什么的
min_rec_mask
该记录是否为B+树中非叶子节点的最小记录
n_owned
在页面内为了快速搜索(二分查找)会分组
只有组内最大记录此字段有值,记录组内记录数,除了
最小记录,大小一般在4-8区间
heap_no
后面我们会说到记录在页面内其实会组成一个
单链表,从头到尾,此属性依次增加.最小记录为0,最大记录为1,真正记录的这个值从2开始
record_type
页内记录类型,目前有四种类型
0就是我们的一般意义上的记录,1是索引用到的,后面再说
2是最小记录、3 是最大记录
next_record
本记录的真正数据到下一条记录的真正数据的偏移量(可以当做存了个指针,向后是额外信息,向前是具体的列)
根据这个属性,页面内所有记录都串了一个单链表
单链表按主键排序,从小到大,最小记录与最大记录分别为头结点和尾节点
四、正式数据部分
| 列名 | 是否必须 | 占用空间 | 描述 |
|---|---|---|---|
row_id |
否 | 6字节 | 行ID,唯一标识一条记录 |
transaction_id |
是 | 6字节 | 事务ID |
roll_pointer |
是 | 7字节 | 回滚指针 |
这三个的位置在真正数据的最开始位置, 属于MySQL为我们添加的隐藏列,不过也不是所有的情况都添加:
表中没有指定主键且没有Unique列,
MySQL会为我们添加一个row_id 作为主键其他两个每条记录都会默认添加
trx_id其实就是事务ID,这个是在五号表空间的全局变量roll_pointer回滚指针,指向一条undo日志记录(在undo日志记录页中)
MySQL有个自增的功能,其实是维护了一个全局变量
这个变量存储在系统表空间的7号表(
7号表空间)中,随着记录的插入而自增, 每逢256的倍数就刷到磁盘中重启系统取出后加上256再赋予给自增列, 因为库中可能已经超过了刷到磁盘中的这个值
最后一点, 强扭的瓜不仅不甜也不解渴, 所以没看懂就不要勉强......
来源:oschina
链接:https://my.oschina.net/u/4350128/blog/3274656