1.page header
page header是page的头信息,占用38个字节,分别存储以下信息: FIL_PAGE_SPACE 4字节 page所属的表空间的space id FIL_PAGE_OFFSET 4字节 page no,一般是在表空间的物理偏移量 FIL_PAGE_PREV 4 字节 前一页的page no (B+tree的叶子节点是通过链表串起来的,有前后关系) FIL_PAGE_NEXT 4字节 后一页的page no FIL_PAGE_LSN 8字节 更改记录时最大的redo log lsn,一般用在redo log恢复时使用 FIL_PAGE_TYPE 2字节 page的类型 FIL_PAGE_FILE_FLUSH_LSN 8字节 space文件最后被flush是的redo log lsn,这个值只会在space的第一个页中被设置 FIL_PAGE_ARCH_LOG_NO 4字节 最后被归档的archive log file 序号,这个值只会在space的第一个页中被设置2.page trailer
page trailer是在文件末尾的最后8个字节, 低位4个字节是用来表示page页中数据的checksum,高位4位是用来存储FIL_PAGE_LSN的部分信息,关于checksum的计算是通过buf_calc_page_checksum这个函数来结算得到的,基本是通过对page中数据作为参数用ut_fold_binary来快速计算得到。在后续的版本中,page checksum是可以选择其他算法来做计算。这两个字在页保存到物理磁盘的时会进行更行,在页从物理磁盘读取出来的时候会被校验。宗旨就是保证页的完整性。3.page body
index page body是由5部分组成,分别是body header、recorders、free recorders、free heap和page directory 组成。body header的结构定义如下:#define PAGE_N_DIR_SLOTS 0 /*page directory拥有的slot个数*/ #define PAGE_HEAP_TOP 2 /*heap中空闲位置的偏移量*/ #define PAGE_N_HEAP 4 /*heap中的记录数,所有分配出去的记录数,free rec + PAGE_N_RECS + 2*/ #define PAGE_FREE 6 /*指向page中空闲空间的偏移量*/ #define PAGE_GARBAGE 8 /*已删除的记录字节数,用于重分配*/ #define PAGE_LAST_INSERT 10 /*最后插入记录的位置*/ #define PAGE_DIRECTION 12 /*记录的操作方向,PAGE_LEFT PAGE_RIGHT PAGE_SAME_REC PAGE_SAME_PAGE PAGE_NO_DIRECTION*/ #define PAGE_N_DIRECTION 14 /*同一方向连续插入的记录数*/ #define PAGE_N_RECS 16 /*页中存在的记录数,不包括infimum和supremum*/ #define PAGE_MAX_TRX_ID 18 /*修改当前页最大的事务ID*/ #define PAGE_HEADER_PRIV_END 26 #define PAGE_LEVEL 28 /*当前页在索引树的层位置*/ #define PAGE_BTR_SEG_LEAF 36 /*B+树叶子节点所在段的segment header信息*/ define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE) /*B+树非叶子节点所在段的segment header信息*/innodb在把真个页可以用的空间当着一个heap,当需要插入记录的时候,首先会在PAGE FREE中找是否有合适的记录 可以用,如果没有,就会在PAGE_HEAP_TOP的偏移上分配一个指定大小的rec_t的记录块,并将记录案主键值插入到 recorders当中。那么recorders是通过什么样的方式组织的呢?
3.1记录的组织方式
在index page body中,rec(记录)组织方式采用的是单向链表的方式来组织的,最前面一个记录和最后面一个记录是innodb定义的虚拟记录,叫做infimum和supremum。这两个记录的物理物质是在body header后面紧接着的连个记录。 其偏移如下:#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE) #define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES) /*本page中索引最小的记录位置*/ #define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8) /*本page中索引最大的记录位置*/这两条记录在index page创建的时候就会被创建,参见page_create函数,其他的记录是插入在其之间,入下示意图:
3.2body free list
除了有效记录以外,page中还有一类是之间使用过但被删除的记录,这类记录不会直接回收到heap中(因为rec是逻辑 顺序关系进行组织的,无法直接回收到heap中),innodb采用了page free recorders列表来组织和管理,通过 body header中的PAGE_FREE来进行定位,PAGE_FREE指向第一个被删除的rec记录的页内偏移量。 示意图如下:
3.3directory slots
innodb为了快速查找记录,在body的后面定义了一个称之为directory的目录槽(slots),每个槽位占用两个字节,采用的是逆序存储,也就是说mifimum的槽位总是在body最后2个字节上,其他的一次类推。每个槽位可以存储多个纪录。以下是各种slot的记录数描述范围(n_owned):| Infimum slot owned |
只有 |