InnoDB数据页结构

521 阅读4分钟

一、InnoDB数据页结构

转载自:www.cnblogs.com/sicheng-li/…

img

1、 file header

img

有一个checksum和LSN;

还有指向下一个页面和上一个页面;

存的都是跟页面有关的信息;

2、 page header

数据页中存储的记录的状态信息,比如:存储了多少条记录,第一条记录的地址是什么,有多少个槽;

3、Infimum和Supremum

两个虚拟的伪记录,分别表示页中的最小和最大记录,占固定的26个字节;

4、 存储过程

img

所以你知道了,User Records 和 Free Space 之间是此消彼长的关系;

举例

create table demo(
   c1 int,
   c2 int,
   c3 varchar(10000),
   primary key(c1)
)charset=ascii row_format=compact

img

简化下,因为变长字段长度列表,null值列表都没什么用;

img

所以存储记录为:

img

* delete_mask:标记是否删除了;

* heap_no:记录的序号,序号为0的记录是infimum,序号1为spuermum(这俩是mysql为我们自动提供的),所以我们自己的都是从2开始的,这个排序是通过主键的比较规则来的;

* next_record:记录下一条记录的偏移量,下一条记录指的是,按照主键值由小到大的下一天记录;

img

假如删除一条数据:

img

那么就等着下一条数据来,直接覆盖就完事了;

提问:为什么指针指的是中间位置,哈哈哈,这就是为什么左边的可变长字段长度列表是逆序的原因了,从中间,往两边同时读,刚好都是顺的。自己画图理解下吧;

5、 page_directory

img

img

将每个组的最大heap_no的记录偏移地址存在page_directory,这样查找的时候,就可以通过page_directory二分查找,然后再进入相应的组中找,美滋滋;

含有Infimum记录的槽的记录数范围:[1],含有Supremum槽的记录数范围为:[1,8],含有用户记录的槽的范围为:[4,8];

6、 file trailer

checksum和LSN;

假如现需要将数据页写入磁盘,写到中途断电了,那么校验和A和校验和B势必不一样,那么就说明出错了,只写了一半;

7、 总结

  1. InnoDB为了不同的目的设计了不同类型的页,我们把用于存放记录的页叫做数据页;

  2. 一个数据页可以被大致分为7个部分,分别是:

    1. File Header:表示页的一些通用信息,占固定的38字节;
    2. Page Header:表示数据页专有的一些信息,占固定的56个字节;
    3. Infimum + Supremum:两个虚拟的伪记录,分别表示页中的最小和最大记录,占固定的26个字节;
    4. User Records:真实存储我们插入的记录的部分,大小不固定;
    5. Free Space:页中尚未使用的部分,大小不确定;
    6. Page Directory:页中的某些记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多;
    7. File Trailer:用于检验页是否完整的部分,占用固定的8个字节;
  3. 每个记录的头信息中都有一个next_record属性,从而使页中的所有记录串联一个单链表;

  4. InnoDB会为把页中的记录划分为若干个组,每个组的最后一个记录的地址偏移量作为一个槽,存放在Page_Directory中,所以在一个页中根据主键查找记录是非常快的:

    1. 根据B+树索引找到对应的数据页,并放入到内存中;(也就是说通过B+树索引只能找到对应的数据页,并不能直接找到对应的记录);
    2. 根据Page Directory进行二分查找,找到对应的槽;
    3. 根据槽中的行记录的单链表结构进行遍历,找到对应的行记录;

    由于(2)(3)步骤是在内存中进行,并且是进行二分查找,时间复杂度很低,因此通常忽略这部分查询所用的时间;

  5. 每个数据页的File Header 部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表;

  6. 为保证从内存中同步到磁盘的页的完整性,在页的首部和尾部都会存储页中数据的校验和和页面最后修改时对应的LSN值,如果首部和尾部的校验和和LSN值校验不成功的话,就说名同步失败了;