目 录CONTENT

文章目录

InnoDB的表空间

FatFish1
2025-05-07 / 0 评论 / 0 点赞 / 18 阅读 / 0 字 / 正在检测是否收录...

页通用结构

在InnoDB数据页部分介绍了类型为FIL_PAGE_INDEX的索引页(数据页)的结构,参考如下链接:

http://www.chymfatfish.cn/archives/InnoDBPage#%E6%95%B0%E6%8D%AE%E9%A1%B5%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84

除了数据页,其他类型的页枚举值如下:

  • FIL_PAGE_TYPE_ALLOCATED |0x0000|最新分配,还没使用

  • FIL_PAGE_UNDO_LOG |0x0002|Undo日志页

  • FIL_PAGE_INODE |0x0003|段信息节点

  • FIL_PAGE_IBUF_FREE_LIST |0x0004|Insert Buffer空闲列表

  • FIL_PAGE_IBUF_BITMAP |0x0005|Insert Buffer位图

  • FIL_PAGE_TYPE_SYS |0x0006|系统页

  • FIL_PAGE_TYPE_TRX_SYS |0x0007|事务系统数据

  • FIL_PAGE_TYPE_FSP_HDR |0x0008|表空间头部信息

  • FIL_PAGE_TYPE_XDES |0x0009|扩展描述页

  • FIL_PAGE_TYPE_BLOB |0x000A|BLOB页

  • FIL_PAGE_INDEX |0x45BF|索引页

这些不同的页,它们的共同结构都是38字节的File Header + 8字节的File Trailer + 16338字节的其他内容

其中File Header之前也看过:

http://www.chymfatfish.cn/archives/InnoDBPage#%E6%96%87%E4%BB%B6%E5%A4%B4%E9%83%A8file-header

而File Trailer用于校验页的完整性的,包括8个字节的固定空间,防止写数据时写了一半停机,回来可以判定这个页是否是完整的

独立表空间结构

区(extent)和组

在InnoDB的文件系统中,一个库就是一个.ibd文件,里面存放的是数据页

一个页16KB,为了管理页,让64个页为1个区extent,因此一个区占1MB;而256个区为一组,即一组有256MB

每个组的第一个区中也是有固定内容的,也就是固定类型的页,其中

组1的extent0中包含一个FIL_PAGE_TYPE_FSP_HDR 、一个FIL_PAGE_IBUF_BITMAP 、一个FIL_PAGE_INODE

后续组中的第一个区extent都是固定包含一个FIL_PAGE_TYPE_XDES 、一个FIL_PAGE_IBUF_BITMAP

  • FIL_PAGE_TYPE_FSP_HDR:用来记录整个表空间(.ibd)文件的整体属性,以及本组所有的区,一个表空间中只有一个该类型的页

  • FIL_PAGE_IBUF_BITMAP:记录该区所有页面的INSERT BUFFER信息

  • FIL_PAGE_INODE:存储INODE结构

  • FIL_PAGE_TYPE_XDES:登记本组中256个区的属性

段segment

段的出现是为了解决查询时随机I/O的问题

如果MySQL的内存空间是完全不连续的,基于B+树查找到一批数据时,需要逐个跳到对应的地址取数,这样就是随机I/O,这样性能是很差的

所以尽量让B+树相邻的节点页的物理地址也相邻,这样可以顺序读取内存,即顺序I/O,性能就好一些

也就是说,引入区的概念,即让64个页具有连续的物理地址

同时,B+树叶子节点里面存放的是真实记录或真实索引列,非叶子节点存的全是目录,如果把叶子节点和非叶子节点分别放到不同的区里面,性能就更好了,因此就有了段的概念,即一个树维护两个段,每个段至少一个区,即一个树2MB的空间

那么具有1个二级索引的表,默认维护两棵树,四个段,至少4MB空间

但是如果维护一个树就要申请2MB,这样申请空间又过于浪费了,因此InnoDB又提出了一个碎片区的概念,这个区中的页,有些归属于段A,有些归属于段B,有些甚至不属于任何段,且碎片区直属于表空间,这样:

  • 在刚开始向表中插入数据时,段是从某个碎片区以单个页面为单位分配存储空间

  • 当一个段已经占用了32个碎片区中的页,就会以完整的区为单位分配空间

区的分类

根据前面段的介绍,可以得到区的状态概念:

  • FREE:空闲区

  • FREE_FRAG:有剩余空间的碎片区

  • FULL_FRAG:没有剩余空间的碎片区

  • FSEG:附属于某个段的区

其中FREE、FREE_FRAG、FULL_FRAG都是独立状态,直属于表空间,而FSEG则是附属于某个段

XDES链表

为了管理一堆区,InnoDB涉及了一个XDES Entry结构,其中存放的是区所属的段ID、一个ListNode链表指向前/后一个XDES Entry,另外就存放区的状态(空闲还是有剩余等)

通过每个XDES Entry和状态的划分,形成了FREE区链表、FREE_FRAG区链表、FULL_FRAG区链表三种链表,这三个是直属于表空间的链表,因此对于所有段来说是共用的

对于FSEG状态的区,也维护了FREE、NOT_FULL、FULL三种链表,分别用于遍历归属于段的空闲页区、归属于段的不满区,归属于段的全满区

因此每个B+树相当于维护了2个段,每个段维护3个归属段的XDES链表,共用3个表空间的XDES链表

如果是具有一个二级索引的表,即相当于聚簇索引、二级索引两个树,维护4个段,即12个归属段的XDES链表,共用3个表空间的XDES链表,即共15个链表

此外,为了方便找到这些链表,把链表中的一个List Base Node放在表空间的固定位置,想要去遍历就好找了

系统表

InnoDB数据字典

InnoDB使用一些内部系统表存储用户表的元数据,包括以下:

  • SYS_TABLES:整个InnoDB存储引擎中所有的表的信息

  • SYS_COLUMNS:整个InnoDB存储引擎中所有的列的信息

  • SYS_INDEXES:整个InnoDB存储引擎中所有的索引的信息

  • SYS_FIELDS:整个InnoDB存储引擎中所有的索引对应的列的信息

  • SYS_FOREIGN:整个InnoDB存储引擎中所有的外键的信息

  • SYS_FOREIGN_COLS:整个InnoDB存储引擎中所有的外键对应列的信息

  • SYS_TABLESPACES:整个InnoDB存储引擎中所有的表空间信息

  • SYS_DATAFILES:整个InnoDB存储引擎中所有的表空间对应文件系统的文件路径信息

  • SYS_VIRTUAL:整个InnoDB存储引擎中所有的虚拟生成列的信息

0

评论区