InnoDB的数据页包含7部分
通用部分
-
Fil Header
-
Page Header
-
Infimum + Supremum Records
-
Page Directory
-
Fil Trailer
数据部分
-
User Records
-
Free Space
数据页有两个 header/trailer对,内部对“页面标题”和“页面目录”主要是 page程序组的关注点,而外部对“ Fil Header”和“ Fil Trailer”主要是 fil程序组的关注点。“ Fil”标题还带有“ File Page Header”的名称。
Fil Header
Fil Header包含8个部分
名称 |
size |
备注 |
|
4 |
页面所在空间的ID |
|
4 |
当前数据页的号码 |
|
4 |
上一页按关键顺序的偏移量 |
|
4 |
按关键顺序下一页的偏移量 |
|
8 |
redo中最新的lsn号码 |
|
2 |
当前定义的类型有: |
|
8 |
checkpoint时刷写到磁盘的日志记录号,仅在文件的第一页上有效 |
|
4 |
|
FIL_PAGE_SPACE
是必需的标识符,因为不同的页面可能属于同一文件中的不同(表)空间FIL_PAGE_PREV 和
FIL_PAGE_NEXT
是页面的双向指针。以两层的B树为例:
- Page Directory 页面的页面目录部分具有可变数量的记录指针,记录指针称为“插槽”或“目录插槽” ,数据页的每六行记录对应一个插槽,插槽slot记录这六行key的最小值
行格式
MySQL目前有4种行格式:Redundant、Compact、Dynamic、Compressed
Version 5.6 已经默认使用 Compact Version 5.7+ 默认使用Dynamic 结构说明: 1、存储单元为页(page),16KB(16384B) 2、每页至少需要存两条数据 3、每条记录都会有记录头 4、每条记录3个隐藏列(6字节的DB_ROW_ID
,6字节的DB_TRX_ID
,7字节的DB_ROLL_PTR
) 5、记录按照聚簇索引组织存储
在内部,InnoDB
向数据库中存储的每一行添加三个字段。6字节的DB_TRX_ID
字段指示插入或更新该行的最后一个事务的事务标识符。此外,删除在内部被视为更新,在该更新中,行中的特殊位被设置为将其标记为已删除。每行还包含一个7字节的 DB_ROLL_PTR
字段,称为滚动指针。回滚指针指向写入回滚段的撤消日志记录。如果行已更新,则撤消日志记录将包含在更新行之前重建行内容所必需的信息。一个6字节的DB_ROW_ID
字段包含一个行ID,该ID在插入新行时会单调增加。如果 InnoDB
自动生成聚集索引,该索引包含行ID值。否则,该 DB_ROW_ID
列不会出现在任何索引中。
Compact
变长字段(记录的长度)列表 + NULL列表 + 记录头信息 + 列值 变长字段(记录的长度)列表:采用1-2个字节来表示一个字段的长度 记录头信息:使用5个字节来表示,主要包含:该记录是否被删除,记录类型,下一条记录的相对偏移量; 隐藏列: rowId,transactionId,rollPointer
Dynamic
与Compact行格式很像,差异在于页面溢出的处理上;
页溢出的处理
因为每页16KB,至少存储两行,所以每行大概有8KB的数据;抛开记录头信息等,大致每列超过768B就会产生页溢出;
compact对于页溢出的处理
1、会将溢出的数据单独放入一个页;外加20B存储额外页的信息(plus the 20-byte pointer to the externally stored part)指向溢出页 2、索引可以使用前768B
dynamic对于页溢出的处理
1、如果页溢出,则使用20B存储整个列信息(列数据都存储在溢出页上)(with the clustered index record containing only a 20-byte pointer to the overflow page) 2、可以使用前3072B字符的索引(--innodb-large-prefix决定)