InnoDB逻辑存储结构

1. InnoDB逻辑存储结构

从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace),表空间又由段(segment)、区(extent)、页(page)组成,页中又包含行的概念(即一条一条的数据)。页在某些文档中被称之为块(block),InnoDB存储引擎的逻辑结构如下
InnoDB逻辑存储结构_第1张图片

2. 表空间

表空间是InnoDB存储引擎逻辑结构的最高层,所有的数据都放在表空间中,默认情况下,InnoDB存储引擎有一个共享表空间ibdata1,即所有的数据都放在这个表空间中。

用户可以通过参数innodb_file_per_table来控制每张表的数据是放在共享表空间中还是放到单独的表空间中。

在这里插入图片描述

如果启动了innodb_file_per_table参数,只会将表的数据,索引和插入缓冲BitMap页存放到单独的表空间中,其他信息,例如回滚(undo),插入缓冲索引页,系统事务信息,二次写缓冲(DOuble write buffer)还是存放于原来的共享表空间内,所以共享表空间还是会不断变大。

共享表空间不会缩小,共享表空间会判断内部的数据是否可用,如果没有用的话就会标记为可用空间,供下次使用。

3. 段

表空间是由各个段组成的,例如数据段,索引段,回滚段等

在InnoDB存储引擎中,对段的管理都是有存储引擎所完成,DBA没有必要对其进行控制,这与Oracle数据库中的自动段空间管理(ASSM)类似,简化了DBA对段的管理。

4. 区

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

InnoDB 1.0x版本开始引入压缩页,即每个页的大小可以通过参数KEY_BLOCK_SIZE自定义页大小,例如2KB,4KB,8KB,因此所对应区的页的梳理为512,256,128.因为区的大小是固定为1M,所以区所对应的页的个数与页大小相关

InnoDB逻辑存储结构_第2张图片
开启KEY_BLOCK_SIZE后,每个数据库都有单独的文件夹,文件夹里有自己的表空间
InnoDB逻辑存储结构_第3张图片

InnoDB逻辑存储结构_第4张图片
例如进入mybatisplus数据库可以看到对应表的ibd文件

4.1 问题

上述提到InnoDB会一次性从磁盘申请4-5个区,那我创建一个新表testcreatetablesize,观察其大小会发现为96KB,上图所示。一个区的大小为1M,idb文件远远小于1M,这是为什么呢?

这是因为在创建表时会先寻找32个页大小的碎片页(fragment page)来存放数据,使用完了之后才是64个连续页的申请,好处是对于小表或者undo这类的段,开始时申请较少的空间,节省磁盘容量的开销。

5. 页

页是InnoDB磁盘管理的最小单位。在InnoDB存储引擎中,默认每个页的大小为16KB,从InnoDB 1.2x版本开始,通过参数innodb_page_size来设置页的大小。如果设置了innodb_page_size,就不可以对其进行修改。InnoDB中常见的页类型有:

  1. 数据页(B-tree node)
  2. undo页(undo log page)
  3. 系统页(system page)
  4. 事务数据页(transaction system page)
  5. 插入缓冲位图页(insert buffer bitmap)
  6. 插入缓冲空闲列表页(insert buffer free list)
  7. 未压缩的二进制大对象页(uncompressed blob page)
  8. 压缩的二进制大对象页(compressed blob page)

5.1 数据页结构

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

5.2 File Header

File Header主要是记录页的一些头部信息,由8个部分组成,共占用38个字节。

File Header详细信息

名称 大小(字节) 说明
FIL_PAGE_SPACE_OR_CHKSUM 4 mysql在4.0.14之前的版本时,改值为0,在之后的版本中,改值代表checksum值,checksum与File Trailer相对应,后续会说明
FIL_PAGE_OFFSET 4 表空间中页的偏移量,FIL_PAGE_OFFSET表示该页在所有页中的位置
FIL_PAGE_PREV 4 当前页的上一个页,因为页是双向列表
FIL_PAGE_NEXT 4 当前页的下一个页
FIL_PAGE_LSN 8 改值代表该页最后被修改的日志序列位置 LSN(log sequence number)
FIL_PAGE_TYPE 2 InnoDB存储引擎页的类型,详细信息见下表
FIL_PAGE_FILE_FLUSH_LSN 8 该值仅在系统表空间中一个页的定义,代表文件至少被更新到了该LSN值,对于独立表空间,改值都为0
FILE_PAGE_ARCH_LOG_NO_OR_SPACE_ID 4 改值代表该页属于哪个表空间

FIL_PAGE_TYPE详细信息说明

名称 十六进制 解释
FIL_PAGE_INDEX 0x45BF B+树叶节点
FIL_PAGE_UNDO_LOG 0x0002 undo log页
FIL_PAGE_INODE ox0003 索引节点
FIL_PAGE_IBUF_FREE_LIST 0x0004 insert buffer 空闲列表
FIL_PAGE_TYPE_ALLOCATED 0x0000 该页为最新分配的
FIL_PAGE_IBUF_BITMAP 0x0005 insert buffer 位图
FIL_PAGE_TYPE_SYS 0x0006 系统页
FIL_PAGE_TYPE_TRX_SYS 0x0007 事务系统数据
FIL_PAGE_TYPE_FSP_HDR 0x0008 file space header
FIL_PAGE_TYPE_XDES 0x0009 扩展描述页
FIL_PAGE_TYPE_BLOB 0x000A BLOB页

5.3 Page Header

该部分用于记录数据页的状态信息,由14个部分组成,共占用56字节
InnoDB逻辑存储结构_第6张图片
InnoDB逻辑存储结构_第7张图片

5.4 Infimum和Supremum Record

在InnoDB存储引擎中,每个数据页都有两个虚拟的行记录,用于限定记录的边界,Infimum记录是比该页中的任何主键值都小的值,Supremum指比任何可能大的值还要大的值。在页创建的时候,这两个虚拟的行记录就会被建立,并且任何情况下都不会被删除,在Compact行格式和Redundant行格式下,其占用的字节数不同

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

5.4 User Record和Free Space

User Record即实际存储行记录的内容
Free Space就是空闲空间,同样也是链表数据结构,在一条记录被删除后,该空间会被加入到空闲链表中

5.5 Page Directory

Page Directory(页目录)中存放了记录的相对位置(这里存放的是页的相对位置,不是偏移量),有时候这些记录指针称为slots(槽)或目录槽(Directory slots)。与其他数据库系统不同的是,在InnoDB中并不是每个记录都拥有一个槽,InnoDB存储引擎的槽是一个稀疏目录(sparse directory)即一个槽中可能包含多个记录。伪记录Infimum的n_owned的值总为1,记录supremum的n_owned的取值范围为【1,8】,其他用户记录n_owned的取值范围为【4,8】当记录被插入或者被删除时需要对槽进行分裂或平衡的维护操作。

在slots中记录按照索引键值顺序存放,这样可以利用二叉查找迅速找到该指针,(只是粗略的结果)具体的精确的结果需要行记录投(record header)中的next_record来继续查找相关记录。

B+树索引不能找到具体的某一条记录,它只能找到对应的页,加载页,通过Page Directory进行二分查找,寻到粗略的位置,再通过record header的next_record来查找到对应的行记录

5.6 File Trailer

为了检查页是否已经完整的写入磁盘(因为有可能从缓冲刷入磁盘时遇到突发情况,例如断电等),InnoDB存储引擎的页中设置了File Trailer部分。
File Trailer只有一个FIL_PAGE_END_LSN部分,占用8个字节。前4个字节代表该页的checksum值,对应File Header的FIL_PAGE_SPACE_OR_CHKSUM的checksum,后4个字节对应File Header的FIL_PAGE_LSN,如果两个都保持一致(注意:checksum是通过checksum函数来进行比较的,不是简单的等值比较),则保证页的完整性。

在默认情况下,InnoDB存储引擎每次从磁盘读取一个页就会检查页的完整性,就是通过File Trailer来进行检测,所以会有一定的开销,可以通过参数innodb_checksums来开启或者关闭对页完整性的检查

在这里插入图片描述

Mysql5.6.6版本新增参数innodb_checksum_algorithm,通过该参数来控制检测函数checksum的算法,默认值为crc32,可以设置的值有innodb、crc32、none、strict_innodb、strict_crc32、strict_non。

在这里插入图片描述

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

6. 行

InnoDB存储引擎和大多数数据库一样,记录是以行的形式进行存储的。InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录,Mysql5.1中默认使用Compact行格式,可以通过命令SHOW TABLE STATUS LIKE 'table_name'来查看表的行格式,其中row_format就是行格式

在这里插入图片描述

6.1 Compact行格式

在这里插入图片描述

边长字段长度列表: 记录非NULL变长字段长度列表(逆序放置),其长度为,若列的长度小于255,则占用1字节,若大于255,则用两个字节表示。

所以varchar类型的最大长度限制为 2^16 - 1 = 65535

NULL标志位: 该为指定了该行数据中是否有NULL值,有则用1表示,该部分占用1字节

记录头信息: 该位置占用5个字节,具体信息如下

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

Total部分就是实际存储每个列的数据,注意:NULL不占用该部分的空间,NULL只会占用NULL标志位。

每行数据除了用户定义的数据外,还有两个隐藏列,分别是事务ID列和回滚指针列,分别占用6字节和7字节,如果InnoDB没有显示的定义主键,且其余的列不符合主键的要求,则会隐式地创建6个字节的rowid列来充当主键,聚簇索引就按照这个rowid来生成。

6.2 Redundant行格式

Redundant是Mysql5.0版本之前InnoDB行记录存储的方式,Mysql5.0支持Redundant是为了兼容之前的版本的页格式。其格式如下:
在这里插入图片描述

字段长度偏移列表: Redundant行记录格式的头部是一个字段长度偏移列表,也是按照列的顺序逆序存储,如果列的长度小于255字节,则用1字节表示,如果大于255字节,则用2字节表示

记录头信息: Redundant行记录头占用6字节,其具体信息如下图所示

InnoDB逻辑存储结构_第11张图片
注意:

  1. n_ields占用10bit,所以mysql数据库的一行最多支持1023列 2^10 -1。

6.3 行数据溢出

InnoDB存储引擎将一条记录的某些列存储在真正的数据页面之外,一般认为BLOB,LOB这类大对象类型会将数据存储在数据页外面。但是这个理解有些偏差,BLOB可以不将数据存放在溢出页面,而且varchar类型数据也有可能出现行溢出。

上述提到varchar类型可以存放65535字节,但是实际上并不能存储65535字节。

InnoDB逻辑存储结构_第12张图片
它提示使用TEXT或者BLOBs来进行存储。

不支持65535字节长度的varchar是因为还会有别的开销,实测varchar可以存储65532字节

InnoDB逻辑存储结构_第13张图片
如果执行上述例子时,没有将SQL_MODE设置为严格模式,可以建立varchar 65535字节成功,但是会有warning,会将varchar转为TEXT

InnoDB逻辑存储结构_第14张图片
上述我们创建的 varchar 65532的字符集是latin1的,如果换位GBK或UTF-8,就不能建立 varchar 65532了。

InnoDB逻辑存储结构_第15张图片
所以可以得出varchar(N)的N指的是字符的长度,上述说的65535指的是字节

注意:varcahr中的65535指的是所varchar的长度和,即一列中varchar的长度和不能超过65535

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

思考一个问题,varchar如果占用的字节最大 65532,但是InnoDB的最小管理单位是页 16KB,即16384字节,这也存不下呀!

一般情况下,InnoDB存储引擎的数据都是存放在页类型为B-Tree node中,上述情况就涉及到了行溢出的概念,当发生行溢出时,数据就存放在页类型为Uncompress BLOB页中

那么varchar多少字节会保留到数据页中,超过多少又会保存到BLOB页中呢?

我们知道页中至少要有两条记录(不然就失去了B+TREE的意义,就变为链表了)。所以如果页中只能存放一条记录,那么InnoDB就会将行数据放到溢出页中

6.4 Compressed与Dynamic行格式

InnoDB1.0X版本引入新的文件格式,以前支持的Compact与Redundant格式称为Antelope文件格式,新的文件格式称为Barracuda文件格式,Barracuda文件格式下拥有两种新的行记录格式,分别是 Compressed与Dynamic

这两种新的行格式对于行溢出的情况采用了完全溢出的方式,如果出现行溢出,则数据页中只存储20字节的指针,实际数据都在Off Page中,而之前的Compact与Redundant两种行格式会存放溢出数据的前768字节

InnoDB逻辑存储结构_第17张图片
Compressed行记录格式的另一个功能:存储在其中Off Page的数据会以zlib算法进行压缩,有效的进行数据的存储

6.5 char的行结构存储

从Mysql4.1版本开始,char(N)中的N指的是字符的长度,而不是之前的字节的长度

InnoDB逻辑存储结构_第18张图片
查看对应所占的字节

InnoDB逻辑存储结构_第19张图片
ab占2字节,我们占4字节

所以可以理解char类型为变长字符类型。

7. Named File Formats机制

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

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