从Page结构来看达梦数据库是不是纯自研
本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客
本文链接地址: 从Page结构来看达梦数据库是不是纯自研
说到达梦数据库,很多人以为都是基于Oracle 8i或者9i的代码copy的;实际上从测试来看并不是这样。这里我要说明,达梦没有给我一毛钱,我不是打广告。这里我通过简单的例子来对了一下窥视:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
SQL> create table killdb(a number,b varchar2(200)) tablespace enmotech; executed successfully used time: 3.444(ms). Execute id is 212. SQL> SQL> insert into killdb values(5,'www.killdb.com'); affect rows 1 used time: 0.525(ms). Execute id is 213. SQL> commit; executed successfully used time: 0.974(ms). Execute id is 214. SQL> select segment_name,SEGMENT_TYPE,HEADER_FILE,HEADER_BLOCK,BYTES,BLOCKS,EXTENTS,INITIAL_EXTENT,MAX_EXTENTS,FREELISTS,FREELIST_GROUPS from dba_Segments where segment_name='KILLDB'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS INITIAL_EXTENT MAX_EXTENTS FREELISTS FREELIST_GROUPS ------------ ------------ ----------- ------------ -------------------- -------------------- -------------------- -------------------- -------------------- --------- --------------- KILLDB TABLE 0 48 262144 32 2 131072 2147483645 NULL NULL used time: 268.345(ms). Execute id is 215. SQL> SQL> DECLARE 2 INFO DBMS_PAGE.DPH_ARR_T; 3 BEGIN INFO = NEW DBMS_PAGE.DPH_T[1]; DBMS_PAGE.DATA_PAGE_HEAD_LOAD(5,0,48,INFO[1]); SELECT * FROM ARRAY INFO; END; 4 5 6 7 8 / N_SLOT N_REC HEAP_LOW HEAP_HIGH BRANCH_NO FREE_LIST_OFF REC_MIN_OFF REC_MAX_OFF EXTERNAL USED_TINYINT ----------- ----------- ----------- ----------- ----------- ------------- ----------- ----------- ----------- ------------ 3 1 138 0 0 NULL 82 90 NULL 152 used time: 0.764(ms). Execute id is 216. SQL> SQL> DECLARE 2 HEAD DBMS_PAGE.DPH_T; 3 INFO dbms_page.REC_ARR_T; 4 BEGIN 5 DBMS_PAGE.DATA_PAGE_HEAD_LOAD(5,0,48,HEAD); 6 INFO = NEW dbms_page.REC_T[HEAD.N_REC]; 7 FOR I IN 1..HEAD.N_REC LOOP 8 DBMS_PAGE.DATA_PAGE_REC_BY_SLOT_NO_LOAD(5,0,48,I,INFO[I]); 9 END LOOP; 10 SELECT * FROM ARRAY INFO; 11 END; /12 SLOT_NO OFFSET LEN IS_DEL TRX_ID CLU_ROWID ROLL_ADDR_FILE ROLL_ADDR_PAGE ROLL_ADDR_OFF ----------- ----------- ----------- ----------- -------------------- -------------------- -------------- -------------- ------------- 1 98 40 0 6029 1 NULL NULL NULL used time: 0.742(ms). Execute id is 223. SQL> set long 9999 SQL> SP_TABLEDEF('SYSDBA','KILLDB'); COLUMN_VALUE ------------------------------------------------------------------------------------------------------- CREATE TABLE "SYSDBA"."KILLDB" ( "A" NUMBER, "B" VARCHAR2(200)) STORAGE(ON "ENMOTECH", CLUSTERBTR) ; used time: 0.427(ms). Execute id is 310. SQL> select dump(a,b) from killdb; select dump(a,b) from killdb; [-6111]:Fail to cast string. used time: 0.652(ms). Execute id is 0. SQL> select dump(a) from killdb; DUMP(A) ------------------ Typ=9 Len=2: 193,6 used time: 0.575(ms). Execute id is 225. SQL> select dump(b) from killdb; DUMP(B) ----------------------------------------------------------------- Typ=2 Len=14: 119,119,119,46,107,105,108,108,100,98,46,99,111,109 used time: 0.527(ms). Execute id is 226. SQL> select group_id,id,path,page_size,FREE_PAGE_NO from v$datafile; GROUP_ID ID PATH PAGE_SIZE FREE_PAGE_NO ----------- ----------- ------------------------------------------- ----------- -------------------- 0 0 /opt/dm/dmdbms/data/enmotech/SYSTEM.DBF 8192 1808 1 0 /opt/dm/dmdbms/data/enmotech/ROLL.DBF 8192 1488 3 0 /opt/dm/dmdbms/data/enmotech/TEMP.DBF 8192 16 4 0 /opt/dm/dmdbms/data/enmotech/MAIN.DBF 8192 48 5 0 /opt/dm/dmdbms/data/enmotech/enmotech01.dbf 8192 64 used time: 0.663(ms). Execute id is 229. SQL> select id,path,MODIFY_TRX from v$datafile; ID PATH MODIFY_TRX ----------- ------------------------------------------- -------------------- 0 /opt/dm/dmdbms/data/enmotech/SYSTEM.DBF 6029 0 /opt/dm/dmdbms/data/enmotech/ROLL.DBF 6029 0 /opt/dm/dmdbms/data/enmotech/TEMP.DBF 6029 0 /opt/dm/dmdbms/data/enmotech/MAIN.DBF 6029 0 /opt/dm/dmdbms/data/enmotech/enmotech01.dbf 6029 used time: 0.577(ms). Execute id is 308. SQL> SQL> select owner,object_name,OBJECT_ID,OBJECT_TYPE,STATUS from dba_objects where object_name='KILLDB'; OWNER OBJECT_NAME OBJECT_ID OBJECT_TYPE STATUS ------ ----------- --------- ----------- ------ SYSDBA KILLDB 1282 TABLE VALID used time: 7.276(ms). Execute id is 232. SQL> select dump(1282) from dual; DUMP(1282) -------------------- Typ=7 Len=4: 2,5,0,0 dmdba@test25:~# dd if=/opt/dm/dmdbms/data/enmotech/enmotech01.dbf bs=8192 skip=48 count=1|od -x 1+0 records in 1+0 records out 8192 bytes (8.2 kB) copied, 6.4457e-05 s, 127 MB/s 0000000 0005 0000 0030 0000 ffff ffff ffff ffff 0000020 ffff ffff 0014 0000 0000 0000 a9af 0000 0000040 0000 0000 0003 008a 0000 0000 0001 ffff 0000060 0052 005a ffff 0098 0000 03ff 0200 0005 0000100 0000 0008 0000 010c 0005 0000 0008 0000 0000120 00c4 0000 0000 0000 0000 ffff ffff ffff 0000140 ffff 2800 8200 06c1 778e 7777 6b2e 6c69 0000160 646c 2e62 6f63 016d 0000 0000 ff00 ffff 0000200 7fff ffff 178d 0000 0000 0000 0000 0000 0000220 0000 0000 0000 0000 0000 0000 0000 0000 * 0017760 0000 005a 0062 0052 0000 0000 0000 0000 0020000 dmdba@test25:~# |
由于x86这里是反向存储,因此c1 06即a列dump value 196,6
778e 7777 6b2e 6c69 646c 2e62 6f63 016d 转换后为:8e77 7777 2e6b 696c 6c64 622e 636f 6d01
其中的77 7777 2e6b 696c 6c64 622e 636f 6d即为我们的数据 www.killdb.com,长度为14。
从dump的page header信息来看,其中:
0005 中 05表示tablespace id 05
第3,4 偏移量为file id 00 00
第6,7偏移量 0030为段头的header page地址,即48
178d 为最近一次修改的事务ID 6029. 类似Oracle checkpoint 。
从dump page的结果来看,在page的尾部没有类似Oracle一样的tail校验机制(block头scn的低位的后4位+block type+seq = block尾部的tail值). 因此从这里也能看出一个问题,如果使用了大于4k的page size,那么达梦数据库也存在partial write问题;换句话说达梦数据库也不支持原子写,而且还没有类似Oracle一样的严格的校验机制。
因此从物理结构来看与Oracle 完全不同,实际上Oracle 8i开始的block结构并没有太大的变化。
所以我认为达梦数据库应该是纯自研,猜测达梦是基于Oracle 8i/9i的说法应该可以洗洗睡了。
不过从相关视图的查询结果来看,达梦基于o的兼容是基于Oracle 12.1进行的。
最后简单总结一下这个小测试得到的几个结论:
1、达梦数据库默认创建的table是簇表,也就是索引组织表,也可以创建为普通堆表;可以参考之前写的文章 达梦数据库学习笔记-表与分区表
2、达梦不支持原子写,也存在partial write问题;
3、达梦不存在类似Oracle一样针对block的严格校验机制(之前已写过类似文章 达梦数据库学习笔记 -达梦IO写入性能与partial write)
4、达梦数据page的结构与Oracle block 结构完全不同,其page头部即存在tablespace id+ file id + header page number;
但是page中的行数据存放格式跟oracle一样,也是row头存放列长度+type+row数据的模式。
Leave a Reply
You must be logged in to post a comment.