InnoDB行记录格式

InnoDB存储引擎和大多数数据库一样,记录是以行的形式存储的。

这意味着页总保存着表中一行行的数据。

InnoDB存储引擎提供了CompactRedundant两种格式来存放行记录数据。

Redundant格式是为兼容之前版本而保留的,CompactMySQL 5.1版本默认的行格式。

可以通过命令 SHOW TABLE STATUS LIKE "table_name" 来查看那当前表使用的行格式。

Compact行记录格式

Compact行记录是在MySQL 5.0中引入的,其设计目标是高效地存储数据。简单来说,

一个页中存放的行数据越多,其性能就越高。

变长字段长度列表 NULL标志位 记录头信息 列1数据 类2数据 ...

Compact行记录格式的首部是一个非NULL变长字段长度列表,并且其是按照列的顺序逆序放置的,

长度为:

  • 若列的长度小于255字节,用1字节表示
  • 若大于255个字节,用2字节表示(所以VARCHAR类型最大长度是65535)

第二部分是NULL标识位,指示了该行数据中是否有NULL值,有则用1表示。

第三部分是记录头信息(record header),固定占用5字节。含义如下:

名称 大小(bit) 描述
() 1 未知
() 1 未知
deleted_flag 1 该行是否已被删除
min_rec_flag 1 为1,如果该记录是预先被定义为最小的记录
啥子?
n_owned 4 该记录拥有的记录数
heap_no 13 索引堆中该记录的排序记录
record_type 3 记录类型,000表示普通,001表示B+树节点指针,010表示Infimun
011表示Supremum,1xx表示保留
next_record 16 页中下一条记录的相对位置
total 40

最后部分就是实际存储每个列的数据。需要特别注意的是,NULL不占该部分任何空间。

此外,每行数据除了用户定义的列外,还有两个隐藏列,事务ID列和回滚指针列,

分别为6字节和7字节的大小。若InnoDB表没有定义主键,每行还会增加一个6字节的rowid列。

Redundant行记录格式

RedundantMySQL 5.0版本之前InnoDB的行记录存储方式。

字段长度偏移列表 记录头信息 列1数据 列2数据 ...

行溢出数据

InnoDB存储引擎可以将一条记录的某些数据存储在真正的数据页面之外。

一般认为BLOBLOB这类的大对象列类型的存储会把数据存放在数据页面之外。

VARCHAR列数据类型也有可能存放为行溢出数据。

InnoDB存储引擎并不支持65535长度的VARCHAR。这是因为还有别的开销,

实际测试发现能存放的最大长度为65532。

InnoDB存储引擎的页为16KB,即16384字节,怎么存储65532字节?

在一般情况下,InnoDB存储引擎的数据都是存放在页类型为B-tree node中,

但当发生行溢出时,数据存放在页类型为Uncompress BOLB页中。

啊,这书里写的,我没试过

MySQL官方手册中定义的65535长度是指所有VARCHAR列的长度总和。

Compressed和Dynamic行记录格式

InnoDB 1.0.x版本开始引入了新的文件格式,以前支持的CompactRedundant格式

称为Antelope文件格式,新的文件格式称为Barracuda文件格式。

Barracuda文件格式拥有两种新的行记录格式:CompressedDynamic

新的两种记录格式对于存放在BLOB中的数据采用了完全的行溢出的方式,在数据页中

值存放20个字节的指针,实际数据存放在Off Page中,而之前的CompactRedundant

两种格式会存放768个前缀字节。

Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,

因此对于BLOBTEXTVARCHAR这类大长度类型的数据能够进行非常有效的存储。

CHAR的行结构存储

MySQL 4.1版本开始,CHR(N)中的N指的是字符的长度,而不是之前版本的字节长度。

也就是在不同的字符集下,CHAR类型列内部存储的可能不是定长的数据。