InnoDB记录结构
1、InnoDB行格式 ?
- 我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为 行格式 或者 记录格式 。
- 设计InnoDB 存储引擎的作者到现在为止设计了4种不同类型的 行格式 ,分别是 Compact 、Redundant 、Dynamic 和 Compressed 行格式。
2、COMPACT行格式 ?
一条完整的记录其实可以被分为 记录的额外信息 和 记录的真实数据 两大部分。
记录的额外信息
这部分信息是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为3类,分别是 变长字段长度列表 、 NULL值列表 和 记录头信息:
- 变长字段长度列表:将一些变长的数据类型,比如 VARCHAR(M),VARBINARY(M),占用的字节数存起来,这些变长字段占的存储空间分为两部分:
- 真正的数据内容
- 占用的字节数
- NULL值列表:Compact 行格式把值为 NULL 的列统一管理起来,存储到 NULL 值列表中。
- 记录头信息:用于描述记录的记录头信息 ,它是由固定的 5 个字节组成。
记录的真实数据
对于 record_format_demo 表来说, 记录的真实数据 除了 c1 、 c2 、 c3 、 c4 这几个我们自己定义的列的数据以外, MySQL 会为每个记录默认的添加一些列(也称为 隐藏列 ),具体的列如下:
3、InnoDB 表对主键的生成策略?
- 优先使用用户自定义主键作为主键,如果用户没有定义主键,则选取一个 Unique 键作为主键,如果表中连 Unique 键都没有定义的话,则 InnoDB 会为表默认添加一个名为row_id 的隐藏列作为主键。
- InnoDB存储引擎会为每条记录都添加
transaction_id
和roll_pointer
这两个列,但是 row_id 是可选的(在没有自定义主键以及Unique键的情况下才会添加该列)。这些隐藏列的值不用我们操心, InnoDB 存储引擎会自己帮我们生成的。
InnoDB数据页结构
1、InnoDB页介绍一下?
- InnoDB 是一个将表中的数据存储到磁盘上的存储引擎,当我们想从表中获取某些记录时,InnoDB 采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB 内容刷新到磁盘中。
- InnoDB 为了不同的目的而设计了许多种不同类型的页 ,比如存放表空间头部信息的页,存放 Insert Buffer 信息的页,存放 INODE 信息的页,存放 undo 日志信息的页。存放我们表中记录的那种类型的被称为索引( INDEX )页。
2、InnoDB数据页的大小为什么是16KB?
- 在操作系统的文件管理系统中进行一次IO读写,默认读取的大小为4kb(一页)。
- 又因为局部性原理,操作系统会将命中的页周围的三块页一同加载进Innodb的缓存池中,因此Innnodb数据页的大小为16kb。
3、数据页结构?
数据页代表的这块 16KB 大小的存储空间可以被划分为多个部分,不同部分有不同的功能,各个部分如图所示:
4、数据页中查找指定主键值的过程?
在一个数据页中查找指定主键值的记录的过程分为两步:
- 通过二分法确定该记录所在的槽,并找到该槽中主键值最小的那条记录。
- 通过记录的 next_record 属性遍历该槽所在的组中的各个记录。
5、数据页总结
- InnoDB为了不同的目的而设计了不同类型的页,我们把用于存放记录的页叫做 数据页 。
- 一个数据页可以被大致划分为7个部分,分别是
- File Header ,表示页的一些通用信息,占固定的38字节。
- Page Header ,表示数据页专有的一些信息,占固定的56个字节。
- Infimum + Supremum ,两个虚拟的伪记录,分别表示页中的最小和最大记录,占固定的 26 个字节。
- User Records :真实存储我们插入的记录的部分,大小不固定。
- Free Space :页中尚未使用的部分,大小不确定。
- Page Directory :页中的某些记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多。
- File Trailer :用于检验页是否完整的部分,占用固定的8个字节。
- 每个记录的头信息中都有一个 next_record 属性,从而使页中的所有记录串联成一个单链表 。
- InnoDB 会为把页中的记录划分为若干个组,每个组的最后一个记录的地址偏移量作为一个槽 ,存放在Page Directory 中,所以在一个页中根据主键查找记录是非常快的,分为两步:
- 通过二分法确定该记录所在的槽。
- 通过记录的next_record属性遍历该槽所在的组中的各个记录。
- 每个数据页的 File Header 部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表 。
- 为保证从内存中同步到磁盘的页的完整性,在页的首部和尾部都会存储页中数据的校验和和页面最后修改时
对应的 LSN 值,如果首部和尾部的校验和和 LSN 值校验不成功的话,就说明同步过程出现了问题。