头图

InnoDB-数据页

前言

大家好,我是xicheng。最近天气变凉,注意身体。现在继续更新MySQL的InnoDB的相关文章,InnoDB的知识脑图如下所示,大家坐稳了。

InnoDB页简介

默认是16KB。大小只能在第一次初始化MySQL数据目录时指定。是InnoDB用于存放数据与索引的页。

InnoDB数据页大体结构

名称中文名大小(字节)简单描述
File Header文件头38页的一些通用信息
Page Header页头56数据页专有的一些信息
Infimum + SupreMum最小记录和最大记录26两个虚拟的行记录
User Records用户记录不确定实际存储的行记录内容
Free Space空闲空间不确定页中尚未使用的空间
Page Directory页目录不确定页中某些记录的相对位置
File Trailer文件尾部8检验页是否完整

如下图所示

File Header

用来记录页的一些头信息。针对各种类型的页都通用File Header属性如下表所示。*为重点掌握的属性。

名称占用空间(字节)描述
*FIL_PAGE_SPACE_OR_CHKSUM4⻚的校验和(checksum值)
*FIL_PAGE_OFFSET4⻚号
*FIL_PAGE_PREV4上⼀个⻚的⻚号
*FIL_PAGE_NEXT4下⼀个⻚的⻚号。通过该属性与FIL_PAGE_PREV属性,实现了B+树中,叶子结点是由双向链表构成,能快速遍历的特性。
FIL_PAGE_LSN8⻚⾯被最后修改时对应的⽇志序列位置
*FIL_PAGE_TYPE2该⻚的类型。具体页类型在下表中展示
FIL_PAGE_FILE_FLUSH_LSN8仅在系统表空间的⼀个⻚中定义,代表⽂件⾄少被刷新到了对应的LSN值
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID4⻚属于哪个表空间

页类型,*为重点掌握的页类型。

类型名称十六进制描述
FIL_PAGE_TYPE_ALLOCATED0x0000最新分配,还没使⽤
*FIL_PAGE_UNDO_LOG0x0002Undo⽇志⻚
*FIL_PAGE_INODE0x0003段信息节点
*FIL_PAGE_IBUF_FREE_LIST0x0004Insert Buffer 空闲列表
FIL_PAGE_IBUF_BITMAP0x0005Insert Buffer 位图
*FIL_PAGE_TYPE_SYS0x0006系统⻚
FIL_PAGE_TYPE_TRX_SYS0x0007事务系统数据
FIL_PAGE_TYPE_FSP_HDR0x0008表空间头部信息
FIL_PAGE_TYPE_XDES0x0009扩展描述⻚
FIL_PAGE_TYPE_BLOB0x000ABLOB⻚
*FIL_PAGE_INDEX0x45BF索引⻚,也就是我们所说的数据⻚

Page Header

上文列举出了很多种类型的页。其中数据页的属性如下表所示。

状态名称大小(字节)描述
PAGE_N_DIR_SLOTS2在⻚⽬录中的槽数量,在Page Directory中会讲到
PAGE_HEAP_TOP2还未使⽤的空间最⼩地址,也就是说从该地址之后就是Free Space
PAGE_N_HEAP2本⻚中的记录的数量(包括最⼩和最⼤记录以及标记为删除的记录)
PAGE_FREE2第⼀个已经标记为删除的记录地址(各个已删除的记录通过next_record也会组成⼀个单链表,这个单链表中的记录可以被重新利⽤)
PAGE_GARBAGE2已删除记录占⽤的字节数
PAGE_LAST_INSERT2最后插⼊记录的位置
PAGE_DIRECTION2记录插⼊的⽅向
PAGE_N_DIRECTION2⼀个⽅向连续插⼊的记录数量
PAGE_N_RECS2该⻚中记录的数量(不包括最⼩和最⼤记录以及被标记为删除的记录)
PAGE_MAX_TRX_ID8修改当前⻚的最⼤事务ID,该值仅在⼆级索引中定义
PAGE_LEVEL2当前⻚在B+树中所处的层级
PAGE_INDEX_ID8索引ID,表示当前⻚属于哪个索引
PAGE_BTR_SEG_LEAF10B+树叶⼦段的头部信息,仅在B+树的根⻚面定义
PAGE_BTR_SEG_TOP10B+树⾮叶⼦段的头部信息,仅在B+树的根⻚面定义

Infimum Record和Supremum Record

每个数据页都有两个虚拟的行记录,用来限定记录的边界。Infimum比该页的任何主键值都小。Supremum比该页的任何主键值都大。如下图所示。

User Record和Free Space

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

Page Directory

数据页的Page Directory用于在页内快速查找某条记录。
分组流程

  1. 初始情况下⼀个数据⻚⾥只有最⼩记录和最⼤记录两条记录,它们分属于两个分组。
  2. 最⼩记录所在的分组只能有1条记录,最⼤记录所在的分组拥有的记录条数只能在1-8条,剩下的分组中记录的条数范围只能在是4-8条之间。
  3. 将每个组的最后⼀条记录的地址偏移量按照从小到大的顺序存储到Page Directory里。Page Directory的这些地址偏移量被称为槽。
  4. 之后每插⼊⼀条记录,都会从⻚⽬录中找到主键值⽐本记录的主键值⼤并且差值最⼩的槽,然后把该槽对应的记录的n_owned值+1,表示本组内⼜添加了⼀条记录,直到该组中的记录数等于8个为止。
  5. 在⼀个组中的记录数等于8个后再插⼊⼀条记录时,会将组中的记录拆分成两个组,⼀个组中4条记录,另⼀个5条记录。这个过程会更新当前组对应的槽,且另外会新增⼀个槽来记录这个新增分组中最⼤的那条记录的偏移量。

示例

  1. 初始情况如下图所示,下图中行记录中属性的含义参见“InnoDB与其它存储引擎--InnoDB的行--COMPACT”。该页有2个组。第1组,也就是Infimum Record所在的组只有1条记录。第2组,也就是Supreme Record所在的组有7条记录。
  2. 插入1条主键值为2的记录:槽1所指的记录的主键值比待插入记录大,且差值最小。将该组的主键最大记录的n_owned +1。也就是将Supreme Record记录的n_owned +1。然后调整next record指针,调整heap no。结果如下图所示。
  3. 插入1条主键值为3的记录。槽1所指的记录的主键值比待插入记录大,且差值最小。此时,槽1对应的组已经有8条记录了。则将该组拆分为2组。更新这2组的heap_no,next_record,槽等信息。进一步简化后的示意图如下所示。

⻚中查找指定主键值的记录流程

  1. 通过⼆分法比较槽所指记录的主键值与待查键值的大小,来确定待查记录所在的槽。
  2. 确定槽后,从槽所指的记录开始,通过记录的next_record属性遍历该槽所在的组中的各个记录,至到找到指定主键的记录,或者遍历完整个组为止。

File Trailer

所有页类型的File Trailer都相同,一共有8个字节,分成2个部分。

前4个字节代表⻚的校验和(checksum),这个部分和FileHeader中FIL_PAGE_SPACE_OR_CHKSUM相对应的。具体通过InnoDB的checksum函数来运算两者,将运算结果进行比较。如果结果相同,才代表页面被完整的刷新到了磁盘。(因为刷盘是先刷File Header,后刷File Trailer)

后4个字节与File Header中的FIL_PAGE_LSN相同,这个部分也是为了校验⻚的完整性的。

结尾

MySQL数据页就讲完了,希望大家能持续关注下去。下一篇MySQL文章讲InnoDB-表空间。

微信扫描下方二维码,或搜索“xicheng”,关注公众号后回复【笔记】,有我准备的15万字Java面试笔记。
图片
  感谢各位人才的点赞、收藏和评论,干货文章持续更新中,下篇文章再见!

一个互联网从业者,一起聊工作,聊生活。

1 声望
0 粉丝
0 条评论
推荐阅读
InnoDB-数据目录
以MySQL8.0为例,不同版本可能会有出入。通过SHOW VARIABLES LIKE 'datadir'查看数据目录。InnoDB和MyISAM这两种存储引擎,创建一个数据库时,会在数据目录下创建一个与数据库同名的文件夹。

西城阅读 649

封面图
一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go34阅读 2.6k评论 1

封面图
SegmentFault 思否面试闯关挑战赛!
“金三银四”求职季到啦,能力自查与提升迫在眉睫🔥 社区专栏与技术问答联合推出: SegmentFault 思否面试闯关挑战赛 本期挑战赛于 3 月 7 日 正式开赛,共设四重关卡,不限技术方向。快来和小伙伴们一起主动追击,...

SegmentFault思否13阅读 10.6k评论 16

封面图
万字详解,吃透 MongoDB!
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的。MongoDB 提供了 面向文档 的存储方式,操作起来比较简单和容易,支持“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常...

JavaGuide8阅读 1.7k

封面图
万字长文~vue+express+mysql带你彻底搞懂项目中的权限控制(附所有源码)
所谓的权限,其实指的就是:用户是否能看到,以及是否允许其对数据进行增删改查的操作,因为现在开发项目的主流方式是前后端分离,所以整个项目的权限是后端权限控制搭配前端权限控制共同实现的

水冗水孚11阅读 1.5k

如何写一个让面试官满意的 Generator 执行器?
例子都可以在 Console 中运行的(谷歌版本 76.0.3809.100),都是以最新浏览器支持的 JavaScript 特性来编写的,不考虑兼容性。

Samon12阅读 3.8k

花了几个月时间把 MySQL 重新巩固了一遍,梳理了一篇几万字 “超硬核” 的保姆式学习教程!(持续更新中~)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。

民工哥11阅读 1.1k

封面图

一个互联网从业者,一起聊工作,聊生活。

1 声望
0 粉丝
宣传栏