InnoDB逻辑存储结构

目录

一、InnoDB存储结构

1. 表空间(Tablespace) 

2. 段(Segment)

3. 区(Extent)

4. 页(Page)

5. 行(Row)

二、InnoDB行记录格式

1. Compact格式

2. Redundant格式

3. Dynamic格式

4. Compressed格式

5. 行格式对比

三、InnoDB数据页结构

1. File Header(文件头)

2.  Page Header(页头)

3.  Infimum和Supremum Records(最小/最大虚拟行记录) 

4. User Records(用户记录)

5. Free Space(空闲空间)

6. Page Directory(页目录)

7. File Trailer(文件结尾信息)

四、参考资料


一、InnoDB存储结构

        InnoDB存储引擎中,表记录都是根据主键顺序组织存放,这种存储方式的表称为索引组织表(index organized table)。每张表都有主键(隐藏列rowId),如果没有显式定义主键,则InnoDB存储引擎会自动创建6字节大小主键。

        InnoDB存储引擎的所有数据都被逻辑地存放一个空间中,称为表空间(tablespace)。表空间由段(segment)、区(extent)、页(page)、行(row)组成,如下图所示InnoDB的逻辑存储结构。

InnoDB逻辑存储结构_第1张图片 InnoDB的逻辑存储结构

1. 表空间(Tablespace) 

        表空间是InnoDB逻辑结构的最高层,所有的数据都放在表空间中。默认情况下,InnoDB存储引擎都有一个共享表空间ibdata1(数据目录下),即所有表的数据都存放在ibdata1空间内。通过innodb_data_file_path参数,可以定义多文件为一个表空间,默认数据目录下ibdata1文件。

        如果启用了innodb_file_per_table参数(默认开启ON),每张表都有自己的独立表空间。独立表空间存放的只是数据、索引和插入缓冲Bitmap页,其它类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息、二次写缓冲等还是存放在原来的共享表空间。

2. 段(Segment)

        表空间由各个段组成,常见的段:数据段、索引段、回滚段。

  • 数据段:B+树的叶子节点(Leaf node segment)
  • 索引段:B+树的非叶子节点(Non-Leaf node segment)
  • 回滚段:undo信息

        InnoDB存储引擎表是索引组织的,因此数据即索引,索引即数据。对段的管理是由引擎自身完成。

3. 区(Extent)

        区是由连续页组成的空间,在任何情况下每个区的大小都为1MB。为了保证区中页的连续性,InonoDB存储引擎一次从磁盘申请4-5个区。在默认情况下,InnoDB存储引擎的页的大小为16KB,即一个区中应有64个连续的页。

        参数innodb_page_size控制页的大小,默认16KB。可以设置4K、8K,此时数据页不是压缩页,这是区中的页数分别为256、128。注意无论页的大小怎么变化,区大小总是1MB。

        启用了innodb_file_per_table参数,每个表有自己的表空间。当创建表没有任何数据时,表空间大小96KB(6个连续页)。为什么不是1MB(一个区的大小)呢?原因是每个段开始时,先用32个碎片页(fragment page)来存放数据,用完后,新页则采用区的方式申请。这样做的目的:对于一些小表,开始时申请较少的空间,来节省磁盘容量的开销。如下代码,是初始化大小。

mysql> SHOW CREATE TABLE test_init_table\G;
*************************** 1. row ***************************
       Table: test_init_table
Create Table: CREATE TABLE `test_init_table` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

ERROR: 
No query specified

mysql> 
mysql> 
mysql> system ls -lh /home/MySQL5.7/mysql-5.7.35/data/test_mysql/test_init_table.ibd;
-rw-r----- 1 mysql mysql 96K Jul 26 02:03 /home/MySQL5.7/mysql-5.7.35/data/test_mysql/test_init_table.ibd

        使用py_innodb_page_info.py脚本工具,查询页的信息:总页数为6,6 * 16KB = 96KB。

[root@488c1daa7967 py_innodb_page_info]# python py_innodb_page_info.py -v /home/MySQL5.7/mysql-5.7.35/data/test_mysql/test_init_table.ibd
page offset 00000000, page type 
page offset 00000001, page type 
page offset 00000002, page type 
page offset 00000003, page type , page level <0000>
page offset 00000000, page type 
page offset 00000000, page type 
Total number of page: 6:
Freshly Allocated Page: 2
Insert Buffer Bitmap: 1
File Space Header: 1
B-tree Node: 1
File Segment inode: 1

4. 页(Page)

        页,也称块(block),是InnoDB磁盘管理的最小单元。静态参数innodb_page_size控制页的大小,默认16KB。可以设置4K、8K。InnoDB存储引擎中,常见的页类型有:

  • 数据页 (B-tree Node)
  • undo页 (undo Log Page)
  • 系统页 (System Page)
  • 事务数据页 (Transaction System Page)
  • 插入缓冲位图页 (Insert Buffer Bitmap)
  • 插入缓冲空闲列表页 (Insert Buffer Free List)
  • 未压缩的二进制大对象页 (Uncompressed BLOB Page)
  • 压缩的二进制大对象页 (compressed BLOB Page)

5. 行(Row)

        InnoDB存储引擎是面向列的(row-oriented),则按行进行存放。每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-200。

        每页最少存储2行记录,用链表连接起来,否则会失去B+树的意义。数据大的行记录,如:大字符串、TEXT、BLOB对象,都是采用行溢出数据存储。不同的行格式,存储方式不同,详细情况见下章节。

二、InnoDB行记录格式

         行记录格式名称都是取自动物的名字,并按照字母顺序排序,且后一个格式支持前一个格式。参数innodb_file_format查看当前支持的行格式。MySQL5.7版本的行格式是Barracuda,同时支持之前的格式Antelope。不同格式的特性,详细参考地址:MySQL :: MySQL 5.7 Reference Manual :: 14.11 InnoDB Row Formats

mysql> show variables like 'innodb_file_format';
+--------------------+-----------+
| Variable_name      | Value     |
+--------------------+-----------+
| innodb_file_format | Barracuda |
+--------------------+-----------+
1 row in set (0.02 sec)

1. Compact格式

        Compact是MySQL5.0引入,目的是高效的存储数据:页中行数据越多,则性能越高。如下图所示,是Compact存储方式。

InnoDB逻辑存储结构_第2张图片

       行格式的首部是个非NULL的变长字段长度列表,且按列的顺序逆序放置,长度为:

  • 列的长度 < 255Byte,则用1Byte
  • 列的长度 >= 255Byte,则用2Byte

        NULL标记位占2Byte,例如:NULL标记位的值06,转为二进制00000110,为1值的位表示第2列和第3列的值为NULL。注意,列值为NULL时,不占用任何位置。无论CHAR或VARCHAR类型,compact格式下NULL值不占任何存储空间

        下表是Compact格式的记录头信息(5Byte)。记录是以堆的形式存放;n_owned是页目录slots中的记录数;每个记录通过next_record找到下一个记录的相对位置,即:页中的行链表的形式链接。

InnoDB逻辑存储结构_第3张图片 Compact记录头信息

        列数据,是按列的顺序放置,注意:NULL值的列不占用任何存储空间。有3个隐藏列:事务ID(6Byte) 、回滚指针(7Byte)、rowid(6Byte)

        大VARCHAR、TEXT、BOLB类型,一部分存储在数据页(B-tree node),另一部分数据存储在数据页之外(行溢出数据),指针指向页类型为未压缩二进制大对象页(Uncompress BLOB)

2. Redundant格式

        Redundant是MySQL5.0之前的格式,如下图所示。

        与Compact不同之处: 

  • 没有NULL标志位
  • 记录头信息大小是6Byte,如下表所示;
  • CHAR类型的NULL值的列,占用存储空间;VARCHAR不占用空间(与Compact相同)

InnoDB逻辑存储结构_第4张图片

3. Dynamic格式

        Dynamic格式是Compact的升级版。大VARCHAR、TEXT、BOLB类型,采用完全的行溢出方式,20字节的指针指向Off Page。

4. Compressed格式

        Compressed格式是Compact的升级版。大VARCHAR、TEXT、BOLB类型,采用完全的行溢出方式,20字节的指针指向Off Page。另外一功能,行数据以zlib的算法进行压缩,即:压缩页

5. 行格式对比

InnoDB逻辑存储结构_第5张图片

文件格式 行格式 特点

Antelope

(羚羊)

Compact

(紧凑)

1. 目的:高效存储数据,即:页中行越多,则性能越大

2. 行格式:变长字段长度偏移列表(1或2字节)

       + NULL标记位(1字节) + 记录头信息(5字节)

       + 列数据 ...

       + 隐藏事务ID列(6字节) + 隐藏回滚指针列(7字节)

       + rowid(6字节)

3. 行记录首部是非NULL变长字段,按列顺序逆序放置:

    列长度小于255字节,用1字节表示;

               大于255字节,用2字节表示;

4. CHAR或VARCHAR类型,NULL值的列不占任何空间

5. 行中有NULL值的列,NULL标记位(转二进制)中该列的位置位则为1,否则0;

6. 固定长度CHAR未能完全占用,则用0x20填充

7. 大VARCHAR、TEXT、BOLB类型,部分数据存储在数据页之外(行溢出数据),指针指向另存的未压缩二进制大对象页(Uncompress BLOB)

Redundant

(冗余)

1. 行格式:字段长度偏移列表(1或2字节)

       + 记录头信息(6字节)

       + 列数据 ...

       + 隐藏事务ID列(6字节) + 隐藏回滚指针列(7字节)

       + rowid(6字节);

2. 没有NULL标志位,与Compact不同:CHAR的NULL值占用空间;VARCHAR的NULL值不占用空间

3. 大VARCHAR、TEXT、BOLB类型,部分数据存储在数据页之外(行溢出数据),指针指向另存的未压缩二进制大对象页(Uncompress BLOB)。

Barracuda

(梭子鱼)

包括Antelope

Dynamic

(动态)

1. 行格式:Compact升级版;

2. 大VARCHAR、TEXT、BOLB类型,采用完全的行溢出方式,20字节的指针指向Off Page。

Compressed

(压缩)

1. 行格式:Compact升级版;

2. 行记录以zlib的算法进行压缩

3. 大VARCHAR、TEXT、BOLB类型,采用完全的行溢出方式,20字节的指针指向Off Page。

三、InnoDB数据页结构

        页,也称块(block),是InnoDB磁盘管理的最小单元。页类型为B-tree node的页存放的即是表中行的数据。下图所示,是InnoDB存储引擎数据页结构。其中File Header、Page Header、File Trailer的大小固定,分别是38Byte、56Byte、8Byte,其他的大小都是动态。

InnoDB逻辑存储结构_第6张图片

        InnoDB数据页结构,有7部分组成,如下表所示。

组成 描述
File Header(文件头) 页的一些头信息,如:该页的偏移量、上下页相对位置、LSN等
Page Header(页头) 页的状态信息,如:页在索引中的位置、最大事务ID、slots数

Infimum和Supremum Records

(最小/最大虚拟行记录) 

1. 虚拟的行,用来限定User Records的边界

2. Infimum记录比该页中任何主键值都要小的值;

    Supremum记录比该页中任何主键值都要大的值;

3. 虚拟记录,在页被创建时被建立,任何情况下无法被删除。

User Records(用户记录) 实际存储的行记录数据
Free Space(空闲空间)

1. 空闲空间,用链表数据结构;

2. 当一个记录被删除后,则该空间会被加入到空闲链表

Page Directory(页目录)

1. 存放记录的相对位置(页中的相对位置,不是偏移量);

2. 有些记录指针称为槽(Slots)或目录槽(Directory Slots);

3. 稀疏目录(sparse directory):一个槽中可能包含多个记录

4. Slots中的记录按索引键值顺序存放,二叉查找法找到记录指针

File Trailer(文件结尾信息)

1. 检测页是否完整的写入磁盘(如:磁盘损坏、宕机等)

2. 默认情况下,InnoDB引擎每次从磁盘读取页时,就会检测该页的完整性,由innodb_checksums参数,默认开启ON

3. innodb_checksum_algorithm控制测试checksum函数的算法,默认crc32。

1. File Header(文件头)

        File Header(文件头)用来记录页的头信息,共占用38Byte。下表所示:File Header组成部分、InnoDB引擎页的类型。

InnoDB逻辑存储结构_第7张图片 File Header组成部分
InnoDB逻辑存储结构_第8张图片 InnoDB引擎页的类型

2.  Page Header(页头)

        Page Header(页头)用来记录数据页的状态信息,共占用56Byte。下表所示:Page Header组成部分。

InnoDB逻辑存储结构_第9张图片

3.  Infimum和Supremum Records(最小/最大虚拟行记录) 

        InnoDB引擎中,每个数据页都有虚拟的行记录,用来限定 User Records(行记录)的边界。Infimum记录比该页中任何主键值都要小的值;Supremum记录比该页中任何主键值都要大的值。注意:这两个虚拟记录,在页被创建时被建立,任何情况下无法被删除

InnoDB逻辑存储结构_第10张图片

4. User Records(用户记录)

        User Records(用户记录),也称行记录,实际存储行记录的内容。 InnoDB存储引擎表是索引组织的,总是B+树组织存放数据。

5. Free Space(空闲空间)

        Free Space(空闲空间),指空闲的空间,也是链表数据结构。当一个记录被删除后,则该空间会被加入到空闲链表。

6. Page Directory(页目录)

        Page Directory(页目录) 存放记录的相对位置(页中的相对位置,不是偏移量)。InnoDB中有些记录指针称为槽(Slots)或目录槽(Directory Slots),并不是每个拥有一个槽。页目录是个稀疏目录(sparse directory),即:一个槽中可能包含多个记录。

        Slots中的记录按索引键值顺序存放,目的使用二叉查找法找到记录指针。页目录很好的解释了File Header中的n_owned值的含义,因为有些记录不在页目录中。所以记录查找的过程是如下所示:

  • step1:B+树索引本身不能找到具体的行,而是找到该记录所在的页
  • step2:把页读入内存的缓存池中
  • step3:根据Page Directory进行二叉查找到记录。

7. File Trailer(文件结尾信息)

        File Trailer(文件结尾信息)用来检测页是否完整的写入磁盘(如:磁盘损坏、宕机等)。默认情况下,InnoDB引擎每次从磁盘读取页时,就会检测该页的完整性。参数innodb_checksums控制是否开启页的完整性检查,默认开启ON。

        File Trailer占用8Byte,只有一个FIL_PAGE_END_LSN。前4字节是该页的checksum值,后4字节和File Header的FIL_PAGE_LSN相同。参数innodb_checksum_algorithm控制测试checksum函数的算法,默认crc32。checksum通过指定函数进行比较,是否一致,来完成页的完整性检查。

四、参考资料

MySQL高级进阶:关于InnoDB存储结构,一文深入分析讲解-51CTO.COM

MySQL表(二)-InnoDB 行 记录格式_星光之子0317的博客-CSDN博客_innodb 行记录格式

MySQL :: MySQL 5.7 Reference Manual :: 14.11 InnoDB Row Formats

你可能感兴趣的:(mysql,数据库,mysql)