独立表空间:
一个表一个, 对应数据库的同名文件夹下的 表名.ibd文件, 里面是很多页
页:
大概16kb,管理存储的最小单位.
有各种不同类型的页 , 比如:
- FIL_PAGE_
INDEX
索引页,也就是我们所说的数据页 - FIL_PAGE_
TYPE_ALLOCATED
最新分配,还没使用 - FIL_PAGE_
INODE
段信息节点
页头都有写这个页的类型
除此之外, 页头还有写:
- 上一页,下一页: 记的是页号(
注意是页号不是物理地址, 有号还需要找
) - 属于哪个表空间
- 校验和
- 页号: 唯一标识本页
区(extent),段(segment) ,组
64个连续的页, 是一个区
区的大小是 64*16kb=1M
256个区是一组
如图,
第一组的第一页类型是 FSP_HDR 描述本组的属性和本组的区的属性
第二页第三页也是固定的类型
其他组的开始2页也是固定的类型, 用来描述本组的信息
分区是因为
虽然每页都有下一页上一页的页号, 可以找到那页, 物理上可能隔着好远, 这种给号码取东西的叫随机I/O
, 很慢, 需要避免, 我们需要让相邻的页物理上也尽量近, 这样才能用顺序I/O
比较快
这个连续区域 叫段
做法是:
- 数据才开始插入的时候, 先从碎片区取单个页没来存储
2.页>32个(半个区), 就给这个段分配整个区
一个表至少2 个段: 主键索引的 一个叶子节点, 一个非叶节点,
加一个索引加2个段
3种结构体
1. XDES Entry : 区
全称就是Extent Descriptor Entry,每一个区(64页,1M)都对应着一个XDES Entry结构, 管理着每个区
描述是本区的64个页 是属于哪个段的(也可能还没用到,不属于哪个段,或者是直属表空间的碎片区),本区64页那些还空着, 本区是属于哪个链的(同链一样的状况 满了/没满/全空 属于段直属空间),下一个上一个是谁
- Segment ID 是 段的Id, 当然这个区还没有用到 ,或者是碎片区 这个就没用了
-
List Node
指向上一个XDES Entry, 下一个XDES Entry
这样能找到上一个下一个,就可以把XDES连成双向链表, 表空间里面有这么6种XDES结构体链表:
- 管理直属于表空间的区(就是碎片区)的XDES结构体链表(满/空/未满)
- 管理属于段的区的XDES结构体链表(满/空/未满)
CREATE TABLE t (
c1 INT NOT NULL AUTO_INCREMENT,
c2 VARCHAR(100),
c3 VARCHAR(100),
PRIMARY KEY (c1),# 索引1
KEY idx_c2 (c2) #索引2
)ENGINE=InnoDB;
这样一个2个索引的表 和15个XDES结构体链有关:
3[直属于表空间的链,放不成区的碎片]
+2[2个索引]
* 2[2段:叶子非叶]
* 3[属于段的链]
-
State
记录本区是: 属于 - 某个段的区
- 空闲
- 有剩余的碎片区
- 满的碎片区,
-
Page State Bitmap
描述区内每个页是否空闲
2. List Base Node :双向链表
基节点, 描述一个链表
的
记载了 一个双向链表的 开始 结束 长度
双向链表可以是XDES Entry 结构体(描述一个区的)链表
3. INODE Entry : 段
描述段
的
橙色: 描述哪个段(段号)
蓝色: 三个 XDES Entry 结构体链表的基节点(有链表的开始结束长度)
灰色: 几个零散页面(最多8个)的页号(对应存在直属表空间的碎片区里面的页)
为什么要分组
要把XDES Entry 集中放一页, 一页放多了XDES Entry 放不下(一个XDES Entry固定40字节 ) 所以给区分组
每组第一页是集中放XDES Entry ,集中放的256个XDES Entry 对应组里面256个区
这种页一般都叫XDES页
除了表空间的第一组第一页,叫FSP_HDR页
, 因为它是一个表空间的第一页 除了要记256个XDES Entry 还有其他东西要记
这样 每个区对应的 XDES Entry 都在固定的地方 找起来很快
FSP_HDR页
每个表空间里面只有一个这种页
是第一页
和其他组一样 要记256个XDES Entry, 还有
- 直属表空间的 3个
XDES链
(碎片区的)的基节点List Base Node
- 还未记入任何
XDES链
没初始化的页 -
INODE链
(描述段的)的基节点List Base Node
满/空 2条各一个
INODE页
每个表空间里面只有一个这种页
是第3页
是放本表空间 所有INODE结构体的
但是, 表空间(一个库) 可能有很多索引 段可能有很多, 所以一页可能不够放,
所以INODE页其实也组成双向链表, 每个INODE也都有记着上一页下一页
一个表空间里面有2个 INODE页组成的双向链表, 一个满的 一个空的,
有新的段需要一个INODE的话, 先去空的INODE链表找, 里面没有了 就从表空间的碎片区空闲链里面划一个到 INODE空闲链
索引怎么找到自己的段对应的INODE?
根节点所在的页(数据字典里面有跟节点的页号) 在 页通用的File Header
后面有个Page Head
, 里面记着 非叶节点段 和 叶节点段 对应的 在哪个INODE页(页号),INODE页的哪个位置是这个段对应INODE Entry(偏移量)
是用这个结构体记的
Segment Header
网友评论