MySQL表数据在磁盘上的组织方式详解
MySQL表数据在磁盘上的组织方式详解
本文将深入探讨MySQL表数据在磁盘上的组织方式,从数据页、变长字段存储到表空间和数据区的结构,帮助读者理解InnoDB存储引擎的数据存储机制。
一行数据在磁盘上是如何存储的
在MySQL中,数据存储格式与行存储格式密切相关。以COMPACT格式为例,每一行数据在存储时都会包含一些头字段,用于描述该行数据,然后是各列的具体值。
对于变长字段,如VARCHAR(10),其存储方式较为特殊。例如,假设两行数据分别为"satori a b"和"sato a b",在磁盘上存储时会直接挨在一起,形成"satori a b sato a b"。为了区分这些数据,MySQL会在存储每一行数据时,保存变长字段的长度列表。具体存储格式如下:
0x06 NULL值列表 数据头 satori a b
0x04 NULL值列表 数据头 sato a b
如果一行数据包含多个变长字段,如VARCHAR(10)、VARCHAR(10)、VARCHAR(10)、CHAR(1)、CHAR(1),则变长字段的长度列表会逆序存放。例如,数据"satori sato sa a b"的存储格式为:
0x02 0x04 0x06 NULL值列表 数据头 satori sato sa a b
NULL值的存储
NULL值的存储方式较为特殊,通过二进制位来表示。例如,对于表customer:
CREATE TABLE customer
(
name VARCHAR(10) NOT NULL,
address VARCHAR(20),
gender CHAR(1),
job VARCHAR(30),
school VARCHAR(50)
) ROW_FORMAT = COMPACT;
假设有一行数据"satori NULL m NULL schoolA",其存储格式如下:
0x07 0x06 00000101 数据头 satori NULL m NULL schoolA
其中,变长字段的长度列表逆序存放,NULL值列表也逆序存放,并且以8位为单位存储。
数据头的作用
数据头占用40个比特位,其中:
- 第1个和第2个比特位预留
- 第3个比特位是delete_mask,用于标识数据是否被删除
- 其他位用于记录其他信息,如事务ID等
字符编码和隐藏字段
在数据真正落盘前,需要进行两步处理:
- 根据字符集编码成二进制
- 添加三个隐藏字段:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR
行溢出
当一行数据超过数据页大小时,会发生行溢出。例如,VARCHAR(65532)类型的数据可能需要多个数据页来存储,这些数据页通过链表连接。
数据页的结构
数据页默认大小为16KB,包含多个部分:
- 文件头
- 数据页头
- 最大记录和最小记录
- 数据行区域
- 空闲空间
- 数据页目录
- 文件尾部
表空间和数据区
- 一个逻辑数据库对应一个目录
- 一张表对应一个.ibd文件
- 表空间包含多组数据区,每组256个数据区
- 每个数据区包含64个数据页
- 第一组数据区的前3个数据页用于存放表空间属性等信息
总结
在物理层面,数据库表现为目录和.ibd文件,每个文件包含多组数据区,每组包含256个数据区,每个数据区包含64个数据页,每个数据页包含描述信息和行数据。理解这些物理结构有助于深入掌握MySQL的工作原理。