欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

程序员文章站 2024-01-11 17:04:04
本章将重点分析表的物理存储特征,即数据在表中是如何组织存放的。也就是说,表就是关于特定实体的数据集合,这也是关系型数据库模型的核心。 4.1 索引组织表 在 InnoDB存储引擎中,表都是按照主键顺序存放的,这样的存储方式的表称为索引组织表。如果创建表时没有显式的定义主键,则按照如下方式选择或创建主 ......

重点分析表的物理存储特征,即数据在表中是如何组织存放的。也就是说,表就是关于特定实体的数据集合,这也是关系型数据库模型的核心。

4.1 索引组织表

在 innodb存储引擎中,表都是按照主键顺序存放的,这样的存储方式的表称为索引组织表。如果创建表时没有显式的定义主键,则按照如下方式选择或创建主键:

  • 判断表中是否有非空的唯一索引(unique not null),如果有,则该列即为主键,如果有多个非空的唯一索引,则选择第一个定义索引的作为主键。
  • 如果不符合上述条件,自动创建一个6字节的指针

_rowid 用于查看单个列作为主键的情况,对于多列,无能为力。

4.2 innodb逻辑存储结构

从innodb存储引擎的逻辑存储结构看,所有数据都被逻辑的存放在一个空间中,称之为表空间。表空间由段(segment)、区(extent)、页(page/block 块)组成。

MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

4.2.1 表空间

可以看到,innodb存储引擎逻辑结构的最高层,所有数据都在表空间中。默认情况下,innodb有一个共享表空间(ibdata1),如果启用了参数 innodb_file_per_table,则每张表的数据都可以单独放到一个表空间内。但每张表的表空间内存放的只是数据、索引和插入缓冲 bitmap页。其他类型的数据,如回滚(undo)信息、插入缓冲索引页、系统事务信息、二次写缓冲(doublewrite buffer)还在共享表空间。

innodb存储引擎不会再执行 rollback 时去收缩 ibdata1 这个空间。虽然 innodb 不会回收这个空间,但是会自动判断这些undo 信息是否还需要,如果不需要,则会将这些空间标记为可用空间,供下次undo使用。

4.2.2 段

从上图可知,表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。其中数据段即为b+树的叶子节点(leaf node segment),索引段即为 b+树的非索引节点(non-leaf node segment),回滚段后续单独介绍。

4.2.3 区

区是连续的页组成的空间,在任何情况下,都是1mb。默认情况下,innodb存储引擎页的大小为 16 kb,即一个区中一共有 64 个连续的页。innodb 1.2.x 新增了参数 innodb_page_size ,通过该参数可以将默认页的大小设置为4k,8k,但页中的数据库不是压缩,但无论页的大小怎么变化,区的大小总是1mb

用户启用了参数 innodb_file_per_table后,创建的表的默认大小是96kb,区中有64个连续的页,应该是1m才对啊?因为在每个段开始时,先用32个页大小的碎片页(fragment page)来存放数据,在使用完这些页之后才是64个连续页的申请。这样做的目的是,对一些小表,或undo这类的段,可以在开始时申请较少的空间,节省磁盘开销。

4.2.4 页

页是innodb磁盘管理的最小单位 ,默认一个页大小为16 kb。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)

4.3 innodb行记录格式

innodb 存储引擎的记录是以行的方式存储的。innodb提供了 compact 和 redundant 两种格式来存放行记录数据,redundant 格式是为了兼容之前版本而保留的。在 mysql 5.1 中,默认设置为 compact 格式。

4.3.1 compact 行记录格式

compact 行记录的存储方式如下所示:
MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

 

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

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

接下来是记录头信息(record header),固定占用5个字节,40位,每位的含义如下:

名称 大小(bit) 描述
0 1 未知
0 1 未知
deleted_flag 1

该行是否被删除

min_rec_flag 1 为1,表示该记录是预先被定义为最小的记录
n_owned 4

该记录拥有的记录数

heap_no 13 索引堆中该记录的排序记录
record_type 3 记录类型,000标识普通,001标识b+树节点指针,010标识 infimum,011标识supremum,1xx标识保留
next_record 16 页中下一条记录的相对位置
total 40  

record header 最后两个字节是 next_record,代表下一个记录的偏移量,即当前记录的位置加上偏移量就是下条记录的起始位置。所以innodb存储引擎是在页内部是通过一种链表的结构来串联各个行记录的

 

最后的部分就是实际每个列的数据,null不占用该部分任何空间,即null除了占用null标志位,实际存储不占用任何空间。另外,每行数据除了用户定义的列外,还有两个隐藏列,事务id列和回滚指针列。若表没有定义主键,还会增加一个6字节的rowid列。

4.3.2 redundant 行记录格式

redundant 是 mysql5.0 版本之前 innodb的行记录存储方式。存储格式如下:

MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

 

不同于compact,首部是一个字段长度偏移列表,按照列的顺序逆序放置的。

第二个部分是记录头信息,不同于 compact格式,redundant 的记录头占用6个字节,其中 n_fields 值代表一行中列的数量,占用10 位,很好的解释了为什么 mysql数据库一行支持最多的列为 1023

名称 大小(bit) 描述
0 1 未知
0 1 未知
deleted_flag 1

该行是否被删除

min_rec_flag 1 为1,表示该记录是预先被定义为最小的记录
n_owned 4

该记录拥有的记录数

heap_no 13 索引堆中该记录的排序记录
n_fields 10 记录中列的数量
1byte_offs_flag 1 偏移列表为1字节还是2个字节
next_record 16 页中下一条记录的相对位置
total 48  

redundant 格式 的 char 类型的null值需要占用空间。

4.3.3 行溢出数据(待续……)

4.3.4 compress 和 dynamic 行记录格式(待续……)

4.3.5 char 的行结构存储(待续……)

4.4 innodb数据页结构

innodb 数据页有以下7部分组成:

  • file header(文件头)
  • page header(页头)
  • infimum 和 supremum records
  • user records(用户记录,即行记录)
  • free space(空闲空间)
  • page directory(页目录)MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式
  • file trailer(文件结尾信息)

MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

4.4.1 file header

4.4.2 page header

4.4.3 infimum 和 supremum record

在innodb存储引擎中,每个数据页中有两个虚拟的行记录,用来界定记录的边界。infimum 是比该页中任何主键值都要小的值。supremum 指的是比任何可能打的值还要大的值。这两个值在页创建时被建立,并且任何情况下不会删除。

MySQL体系结构,InnoDB存储引擎表、页结构、行记录格式

 4.4.4 user record 和 free record

user record 是实际存储行记录的内容,而 free space 指的是空闲空间,也是个链表数据结构。在一条记录被删除后,会加入到空闲链表中。

4.4.5 page directory

页目录中存放了记录的相对位置,有时候,这些记录指针被称为slots(槽)或目录槽(directory slots),innodb 存储引擎的槽是一个稀疏目录,即一个槽中有多个记录。

在 innodb中page directory 是稀疏目录,二叉查找的结果只是粗略的结果,因此 innodb 必须通过 record header 中的 next_record 来继续查找相关记录。同时 page directory 很好的解释了 record header 中的 你_ownedzhi的含义,因为这些记录并不包含在 page directory中

需要牢记的是,b+ 树索引本身并不能找到具体的一条记录,能找到的只是该记录所在的页。数据库把页载入内存,然后通过page directory 再进行二叉查找。

4.4.6 file trailer

为了检测页是否已经完整的写入磁盘(如可能发生的写入过程中的磁盘损坏,机器关机等),innodb的页中设置了 file trailer 部分。

4.5 name file formats 机制(待续……)

4.6 约束

4.6.1 数据完整性

一般来说,数据完整性有以下三种形式:

  1. 实体完整性:保证表中有一个主键,用户可通过定义 unique key 或 primary key约束来保证
  2. 域完整性:保证数据每列的值满足特定的条件,如合适的数据类型,外键约束,编写触发器,default约束
  3. 参照完整性:保证两张表之间的关系,如外键或触发器

4.6.2 约束和索引的区别

当用户创建了一个唯一索引就创建了一个唯一的约束。但是约束更像是一个逻辑的概念,用来保证数据的完整性。而索引是一个数据结构,既有逻辑概念,也代表这物理存储的方式。

4.7 视图

视图是一个命名的虚表,,由一个sql 查询来定义,可以当做表使用,视图中的数据没有实际的物理存储。视图在一定程度上起到了一个安全层的作用。

虽然视图是一个虚表,但用户可以对某些视图进行更新操作,本质就是通过视图的定义来更新基本表。

 转自:https://www.cnblogs.com/jjfan0327/p/12695565.html