0
点赞
收藏
分享

微信扫一扫

DM8 数据页格式解析

醉倾城1 2022-04-15 阅读 84
dba

文章目录

数据页结构对于底层存储是重要的内容,可以从中了解一个数据库的架构设计和工作机制,这里我通过一些测试,对比磁盘内容的变化和相关视图信息,大体得出一些较为浅显的内容

完整数据页

首先来看一个数据页是什么样的,由于版本差异其结构体可能发生变化,大体上是下面这样

00000000  04 00 00 00 e0 27 00 00  ff ff ff ff ff ff ff ff  |.....'..........|
00000010  ff ff ff ff 14 00 00 00  00 00 00 00 32 de b3 00  |............2...|
00000020  00 00 00 00 04 00 bc 00  00 00 00 00 02 00 62 00  |..............b.|
00000030  52 00 5a 00 00 00 b0 00  00 00 df 05 00 02 04 00  |R.Z.............|
00000040  00 00 02 08 00 00 fc 04  04 00 00 00 02 08 00 00  |................|
00000050  b4 04 00 00 00 00 00 00  00 00 ff ff ff ff ff ff  |................|
00000060  ff ff 00 1c 00 ff ff 00  00 81 61 01 00 00 00 00  |..........a.....|
00000070  00 ff ff ff ff 7f ff ff  db 85 0b 00 00 00 00 1c  |................|
00000080  00 02 00 00 00 81 62 02  00 00 00 00 00 ff ff ff  |......b.........|
00000090  ff 7f ff ff dc 85 0b 00  00 00 00 22 00 01 00 00  |..........."....|
000000a0  00 87 64 64 64 64 64 64  64 01 00 00 00 00 00 00  |..ddddddd.......|
000000b0  ca 9f 00 00 5b 00 ee 85  0b 00 00 00 00 00 00 00  |....[...........|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001ff0  5a 00 7e 00 9a 00 52 00  00 00 00 00 00 00 00 00  |Z.~...R.........|
00002000

通用页头

页头部分主要包括了页的物理存储信息和类型等

00000000  04 00 00 00 e0 27 00 00  ff ff ff ff ff ff ff ff  |.....'..........|
00000010  ff ff ff ff 14 00 00 00  00 00 00 00 32 de b3 00  |............2...|
00000020  00 00 00 00 

其内容解析为
bit 1-2 TBS NO 4
bit 3-4 FILE NO 0
bit 5-8 PAGE NO 10208
bit 9-10 PREV FILE ID -1
bit 11-14 PREV PAGE NO -1
bit 15-16 NEXT FILE ID -1
bit 17-20 NEXT PAGE NO -1
bit 21-24 PAGE TYPE 20
bit 25-28 CHECK SUM
bit 29-36 LSN 11787826

空间页头

空间页头主要包括页内空间使用情况,便于快速定位到空闲位置和高水位

                      04 00 bc 00  00 00 00 00 02 00 62 00  |..............b.|
00000030  52 00 5a 00 00 00 b0 00

bit 37-38 TBS NO 4
bit 39-40 HEAP LOW 188
bit 41-42 HEAP HIGH 0
bit 43-44 UNKNOWN
bit 45-46 ROW CNT
bit 47-48 LAST FREE LIST
bit 49-56 UNKNOWN

索引页头

索引页头包含了索引相关信息,用于关联索引节点

                                   00 00 df 05 00 02 04 00  |R.Z.............|
00000040  00 00 02 08 00 00 fc 04  04 00 00 00 02 08 00 00  |................|
00000050  b4 04 00 00 00 00 00 00  00 00 ff ff ff ff ff ff  |................|
00000060  ff ff             

bit 57-58 PAGE LEVEL 0
bit 59-62 INDEX_ID(OBJECT_ID) 33555935
bit 63-64 LEAF_SEGMENT_GROUP 4
bit 65-66 LEAF_SEG_FILE_ID 0
bit 67-70 LEAF_SEG_PAGE_NO 2050
bit 71-72 LEAF_SEG_OFFSET 1276
bit 73-74 INNER_SEGMENT_GROUP 4
bit 75-76 INNER_SEG_FILE_ID 0
bit 77-80 INNER_SEG_PAGE_NO 2050
bit 81-82 INNER_SEG_OFFSET 1204
bit 83-97 UNKNOWN

数据行

数据行主要包括数据内容,删除标记,ROWID等,实际内容部分由数据具体格式决定,此处我放了一个包含int和varchar(100)两个字段的行,由于被我进行过update操作,所以会包含指向回滚页信息

                00 1c 00 ff ff 00  00 81 61 01 00 00 00 00  |..........a.....|
00000070  00 ff ff ff ff 7f ff ff  db 85 0b 00 00 00 00 1c  |................|
00000080  00 02 00 00 00 81 62 02  00 00 00 00 00 ff ff ff  |......b.........|
00000090  ff 7f ff ff dc 85 0b 00  00 00 
                                         00 22 00 01 00 00  |..........."....|
000000a0  00 87 64 64 64 64 64 64  64 01 00 00 00 00 00 00  |..ddddddd.......|
000000b0  ca 9f 00 00 5b 00 ee 85  0b 00 00 00 00 00 00 00  |....[...........|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

bit 98-154 OLD DATA (INVALID)
bit 155 DELETE_FLAG 0
bit 156-157 ROWLEN 34
bit 158-161 INT4 DATA 1
bit 162-179 VARCHAR DATA ddddddd
bit 170- 176 ROWID 1
bit 177-180 FPA_PAGE_NO 40906
bit 181-182 FPA_FILE_NO 0
bit 183-184 UNKNOWN 5b 00
bit 185-187 TRXID 755182

有多行数据的时候依次向后即可

回滚页

当对于本行TRXID不满足MVCC可见性条件时,根据已经提交的版本判断合适的TRXID并向对应回滚页读取
在这里插入图片描述
根据信息找到前一个版本位于回滚页40906中,回滚页如下

00000000  01 00 00 00 ca 9f 00 00  ff ff ff ff ff ff ff ff  |................|
00000010  ff ff ff ff 1d 00 00 00  00 00 00 00 33 de b3 00  |............3...|
00000020  00 00 00 00 ee 85 0b 00  00 00 01 37 00 ad 00 07  |...........7....|
00000030  c5 41 ad 3e 24 06 00 24  00 28 00 03 00 00 00 00  |.A.>$..$.(......|
00000040  00 00 00 00 00 00 00 00  00 00 00 16 05 00 ff ff  |................|
00000050  ff ff ff ff ff 00 00 00  00 37 00 32 00 02 01 04  |.........7.2....|
00000060  00 00 00 db 85 0b 00 00  00 00 00 00 00 00 00 16  |................|
00000070  05 00 ff ff ff ff 7f ff  ff 01 00 00 00 00 00 00  |................|
00000080  00 01 00 01 00 01 00 61  00 00 00 5b 00 20 00 12  |.......a...[. ..|
00000090  00 05 00 00 00 ee 85 0b  00 00 00 00 00 00 00 00  |................|
000000a0  00 00 00 00 00 00 00 00  00 00 00 8d 00 8f 90 00  |................|
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002000

由于回滚页完的具体各解法目前我还尚未研究透彻,所以有待以后研究,但目前
根据数据行中的 c9 9f 00 00 5b 00 信息是足够定位到回滚页中行修改前数据如下

                   c9 9f 00 00 5b  00 01 00 00 00 00 00 00  |.......[........|
00000080  00 01 00 01 00 03 00 64  64 64 00 00 00 5b 00

可以看出其中包含下列信息
ROWID 1
修改前数据 1 ddd

偏移量数组

在数据页的末尾,通过偏移量数组记录了每一行数据的起始位置,即SLOT信息

00001ff0  5a 00 7e 00 9a 00 52 00  00 00 00 00 00 00 00 00  |Z.~...R.........|
00002000

如我这里的信息为
HEAD OFFSET 0x52
SLOT1 OFFSET 0x9a
SLOT2 OFFSET 0x7e

DBMS_PAGE

在DM8中提供了DBMS_PAGE这个Package帮助通过预定义的结构体来查看页的信息,这里列举一些常见用法,详细可以根据Package内的方法灵活使用
查看通用页头

SQL> DECLARE
PAGE0 VARBINARY;
PHINFO DBMS_PAGE.PH_T;
PHINFO_ARR DBMS_PAGE.PH_ARR_T;

BEGIN
PHINFO_ARR = NEW DBMS_PAGE.PH_T[1];

DBMS_PAGE.PAGE_LOAD(4,0,10208,PAGE0);
PHINFO_ARR[1] = DBMS_PAGE.PAGE_HEAD_GET(PAGE0);

SELECT * FROM ARRAY PHINFO_ARR;

END; 
/

行号     TS_ID       SELF_FILE_ID SELF_PAGE_NO PREV_FILE_ID PREV_PAGE_NO NEXT_FILE_ID NEXT_PAGE_NO PAGE_TYPE   CHECKSUM   
---------- ----------- ------------ ------------ ------------ ------------ ------------ ------------ ----------- -----------
           LSN                 
           --------------------
1          4           0            10208        -1           -1           -1           -1           20          0
           11838241


已用时间: 1.305(毫秒). 执行号:685000.

查看空间页头

SQL> DECLARE
PHINFO DBMS_PAGE.dps_t;
PHINFO_ARR DBMS_PAGE.DPS_ARR_T;

BEGIN
PHINFO_ARR = NEW DBMS_PAGE.dps_t[1];
PHINFO_ARR[1] = DBMS_PAGE.DATA_PAGE_SPACE_INFO_GET(4,0,10208);

SELECT * FROM ARRAY PHINFO_ARR;

END;
/

行号     HEAP_LOW    HEAP_HIGH   USED_TINYINT FREE_TINYINT USED_RATE   HEAP_HIGH_LEFT FREE_LIST_SIZE FREE_LIST_RATE MAX_REC_ABLE
---------- ----------- ----------- ------------ ------------ ----------- -------------- -------------- -------------- ------------
1          346         0           374          7818         4           7818           0              0              7816

已用时间: 0.252(毫秒). 执行号:685001.

查看索引页头

SQL> DECLARE
PHINFO DBMS_PAGE.dpih_t;
PHINFO_ARR DBMS_PAGE.DPIH_ARR_T;

BEGIN
PHINFO_ARR = NEW DBMS_PAGE.dpih_t[1];
PHINFO_ARR[1] = DBMS_PAGE.data_page_ind_head_get(4,0,10208);

SELECT * FROM ARRAY PHINFO_ARR;

END; 
/

行号     PAGE_LEVEL  INDEX_ID    LEAF_SEG_GROUP_ID LEAF_SEG_FILE_ID LEAF_SEG_PAGE_NO LEAF_SEG_OFFSET INNR_SEG_GROUP_ID INNR_SEG_FILE_ID INNR_SEG_PAGE_NO INNR_SEG_OFFSET
---------- ----------- ----------- ----------------- ---------------- ---------------- --------------- ----------------- ---------------- ---------------- ---------------
1          0           33555935    4                 0                2050             1276            4                 0                2050             1204

已用时间: 0.413(毫秒). 执行号:685002.

查看FREE LIST

SQL> DECLARE
PHINFO DBMS_PAGE.free_list_t;
PHINFO_ARR DBMS_PAGE.FREE_LIST_ARR_T;

BEGIN
PHINFO_ARR = NEW DBMS_PAGE.free_list_t[1];
PHINFO_ARR = DBMS_PAGE.data_page_free_list_get(4,0,10208);

SELECT * FROM ARRAY PHINFO_ARR;

END;
/

行号     OFF         LEN        
---------- ----------- -----------
1          98          28

已用时间: 0.413(毫秒). 执行号:685003.

总结

到此就对DM8数据页的格式做了一个浅薄的介绍,部分位还尚存疑点,需要进一步在工作和实验中进行学习和验证,欢迎了解的同学共同分享。

举报

相关推荐

0 条评论