5. mysql磁盘存储文件

64 阅读3分钟

1. 数据页

innodb存储引擎,把数据组织成一页一页的概念,每一页有16kb,然后每次加载磁盘的数据到内存的时候,是至少加载一页数据进去的,甚至是多页数据进去。

2. 一行数据在磁盘是如何存储的

行格式,使用COMPACT格式

CREATE TABLE table_name (columns) ROW_FORMAT=COMPACT
ALTER TABLE table_name ROW_FORMAT=COMPACT

这种格式下,数据存储的格式类似如下:

[变长字段的长度列表][null值列表][数据头][column1的值,column2的值,columnn的值......]

除了每一个字段的值以外,还包含了一些额外的信息,这些额外的信息就是用来描述这一行数据的。

2.1. 长信息的存储

类如:字段变长与定长混合的表: varchar(10) varchar(5) varchar(20) CHAR(1) CHAR(1)

存储内容为:hello hi hao a a

变长的字段长度分别为:0x05 0x02 0x03

定长字段的长度列表是逆序放的,猜测逆序放是通过压入栈的方式,然后出栈正向读取

对应存储为: [0x03 0x02 0x05] [null值列表] [数据头] [hello hi hao a a]

2.2. NULL值处理

NULL值是以二进制bit为来存储的,表结构如下:

CREATE TABLE customer (
name VARCHAR(10) NOT NULL,
address VARCHAR(20),
gender CHAR(1),
job VARCHAR(30),
school VARCHAR(50)
) ROW_FORMAT=COMPACT;

数据为:jack NULL m NULL xx_school

变长的字段长度:0x04(jack) 0x09(xx_school)

因为表中4个字段可以为null(address,gender,job,school),对应上面的数据为1010,即1是null(address,job),0是非null(gender,school),实际存储是倒序同时是补足8位的。

所以磁盘上的存储为: [0x09 0x04] [00000101] [头字段] [jack m xx_school]

2.3. 40bit的头字段

第一个和第二个bit为,预留位,没有意义

第三位是delete_mask,标识这行数据是否删除

第四位min_rec_mask,b+树里面每一层的非叶子节点的最小值

第五位到第八位,n_owbed,记录数

接下来的13位 heap_no,当前这行数据在记录堆里的位置

然后3位是record_type,数据类型 0:普通类型 1:B+树非叶子节点 2:最小值 3:最大值

16位next_record,下一条指针地址

2.4. 其他字段

DB_ROW_ID,这个行的唯一标识,如果没有指定主键,默认加的ROW_ID为主键

DB_TRX_ID,事务ID

DB_ROLL_PTR,回滚指针

3. 行溢出

当最后的真实数据端存储实际数据的时候,如果出现的内存过大,列如存储了txt类型的数据,会导致超过单页16kb的限制,就会出现行溢出的现象,即数据行页存储。

4. 表空间

我们平时创建的那些表都是有对应的表空间的,每个表空间就是对应磁盘上的数据文件,在表空间里有很多组数据区,一组数据区是256个数据区,每个数据区包含了64个数据页,是1MB,然后表空间的第一组数据区的第一个数据区的头三个数据页,都是存放特殊信息的。

当我们执行crud操作的时候,就是从磁盘上的表空间的数据文件里,去加载一些数据页出来到buffer pool的缓存页里去使用。