七、数据行物理存储格式

  现在我已经知道了,MySQL 的每行数据都存储在数据页上,那为什么需要数据页呢?实际上是为了提高数据的读取效率,把读取的指定数据所在数据页中的其他数据行都一次性写入缓存,避免频繁的磁盘 IO 读取数据。那么每行数据又是如何存储的?又如何知道数据在哪个数据页?在哪个数据区?在哪个表空间呢?

行格式

  实际上在创建表的时候就可以指定它的行存储格式。比如:

CREATE TABLE table_name (columns) ROW_FORMAT=COMPACT 或者修改行格式
ALERT TABLE table_name ROW_FORMAT=COMPACT

  在 compact 行格式下,每行数据存储类似这样的:

变长字段的长度列表,null值列表,数据头,column01的值,column02的值,column0n的值......

  就是对于每一行数据会有一些数据头对这行数据进行描述。

varchar 字段

  MySQL 中允许一些字段的长度是可变的,比如 varchar(10),那么这种字段存储时就是这样的:数据类型为 varchar(10), char(1), char(1) 存储的值为 hello a a 这种,另外一行数据可能为 hi a a 这种,然后存储时就是 hello a a hi a a 两行数据紧挨着存储的以节省存储空间。

  那么这种数据怎么读呢?而且头一个字段还是可变长度的。这时就需要一个可变字段的长度列表,来解决这种数据的读取问题。比如 hello 的实际长度为 5,十六进制就是 0x05。那么这两行存储在文件中就是这样的:

0x05 null值列表 数据头 hello a a 0x02 null 值列表 数据头 hi a a

  然后读取时会首先读取到可变字段长度列表,然后按照长度读取指定长度的数据。那如果有多个可变字段呢?它们的可变长度列表逆序写入文件,也就是这样:

0x03 0x02 0x05 null值列表 头字段 hello hi hao a a

NULL 值字段

  null 值字段怎么存储?存空字符串?空白字符?存“NULL”?这些都是不行的,本来就是 null 为啥还要存呢?所以需要通过另一种方式来表示那个字段是没有值的,是为 null 的。实际上对于 null 不通过字符串直接在磁盘上存储,而是通过二进制 bit 位来存储,不管字段是否为 null,null 值列表都会有这个字段的 bit 位标记(0 不为 null,1 为 null,通常为 8 位,不足8 位用 0 补高位),并且 bit 位以逆序形式存储在 NULL 值列表表示该字段是否为 null 。如果一个可变长度字段值为 null ,那么可变长度列表将不存在这个字段的长度

0x09 0x04 00000101 头信息 column1=value1 column2=value2 ... columnN=valueN

  然后读取时就会根据可变长度和null值列表,读取整行数据。

数据头

  每一行数据存储时还会留有 40 个 bit 位的数据头,用来描述这行数据。其中第一个和第二个是预留的 bit 位,没有任何含义。然后就是

  delete_mask 1个 bit 位,标识这行数据是否被删除,也就是说 MySQL 删除一行记录时不是立刻把这行数据删除,而是留一个 bit 位标识。

  min_rec_mask 1个 bit 位,B+ 树里每一层的非叶子节点里的最小值的标记位。

  n_owned 4个 bit 位,一个记录数

  heap_no 13个 bit 位,表示这行数据在记录堆里的位置

  record_type 3个 bit 位,表示这行数据的类型,0代表的是普通类型,1代表的是B+树非叶子节点,2代表的是最小值数据(伪数据行 Infimum),3代表的是最大值数据(伪数据行 Supremum)

  next_record 16个 bit 位,表示指向下一条数据的指针。

隐藏列

  除了记录每一列对应的数据外,还有隐藏列,它们分别是 Transaction ID、Roll Pointer 以及 row_id(当没有指定主键)。

行溢出

  一行数据是存储在 16kb 大小的数据页上的,如果一行数据存储的内容超过这个数据页的容量,就会把数据溢出到其他数据页去,然后在数据页中存放这个溢出字段的一部分数据,同时包含一个20字节的指针,指向那些存放溢出数据的数据页,这些存放溢出数据的数据页就可以用指针串联起来形成链表,存放这个超大字段里的数据。那些存放溢出数据的数据页就叫做溢出页。像 TEXT 类型、BLOB 类型都有可能发生溢出。

posted @   维维尼~  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示