众所周知,Oracle的数据是储存在数据文件中的。那么Oracle是以什么格式来储存数据的呢?相信大家都对其内部结构很感爱好。这篇文章就帮大家来了解Oracle数据文件的内部结构。
我们知道数据库储存的最小单位是数据块,其他如extent,segment,tablespace等都是由数据块组成,所以我们就从数据块的结构来分析。 典型的数据块由3部分构成: 1. 头信息区 这个区包括数据块的地址,数据块类型,检查点信息,scn信息,数据块版本号等。(以下是其大概的构造,稍后会做解释) ――――――――――――――――――――――――――― *** 2003-06-10 10:05:10.296 Start dump data blocks tsn: 2 file#: 3 minblk 13107 maxblk 13107 buffer tsn: 2 rdba: 0x00c03333 (3/13107) scn: 0x0000.00105d22 seq: 0x05 flg: 0x00 tail: 0x5d220605 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data Block header dump: 0x00c03333 Object id on Block? Y seg/obj: 0x6493 csc: 0x00.105d22 itc: 1 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 ―――――――――――――――――――――――――――― 2. 事务列表区 事务列表去包括了在这个数据块内的事务,也就是我们知道的ITL(interested transaction list),从中我们可以知道XID(transaction id),UBA(undo block address)等信息(以下是其大概的构造,稍后会做解释) --------------------------------------------------------------------------------- Itl Xid Uba Flag Lck Scn/Fsc 0x01 xid: 0x0009.012.00000002 uba: 0x00800c84.0000.25 ---- 1 fsc 0x0000.00000000 --------------------------------------------------------------------------------- 3. 数据区,尾区 数据区顾名思义是真正存储数据的地方,在这里我们可以看到每一条记录。至于尾区,这里储存着数据块的版本号,与数据头信息区的版本号相对应,可以用来确定数据块前后是否一致。 (以下是其大概的构造,稍后会做解释) ――――――――――――――――――――――――――― data_block_dump =============== tsiz: 0x1fb8 hsiz: 0x14 pbl: 0x0f3f7444 bdba: 0x00c03333 flag=----------- ntab=1 nrow=1 frre=-1 fsbo=0x14 fseo=0x1fb2 avsp=0x1f9b tosp=0x1f9b 0xe:pti[0] nrow=1 offs=0 0x12:pri[0] offs=0x1fb2 block_row_dump: tab 0, row 0, @0x1fb2 tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 02(数据就在这里) end_of_block_dump End dump data blocks tsn: 2 file#: 3 minblk 13107 maxblk 13107 ――――――――――――――――――――――――――― 下面我们来做一个完整的实验,首先创建一个新的表空间 SQL> create tablespace testblock datafile 'd:\oracle\oradata\test\testblock.ora' size 100m; 表空间已创建。 创建一个新用户并指定默认表空间为testblock,临时表空间为temp SQL> create user testblock identified by testblock default tablespace testblock temporary tablespace temp; 用户已创建 SQL> grant create session to testblock; 授权成功。 SQL> grant resource to testblock; 授权成功。
SQL> connect testblock/testblock@test 已连接。 SQL> create table testblock (a number); 表已创建。 SQL> insert into testblock values(1); 已创建 1 行。 SQL> insert into testblock values(2); 已创建 1 行。 SQL> commit; 提交完成。 SQL> connect internal/oracle@test 已连接。 SQL> select header_file,header_block from dba_segments where segment_name='TESTBLOCK'; HEADER_FILE HEADER_BLOCK Start dump data blocks tsn: 8 file#: 11 minblk 2 maxblk 2 buffer tsn: 8 rdba: 0x02c00002 (11/2) scn: 0x0000.001148eb seq: 0x01 flg: 0x00 tail: 0x48eb1001 frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED Extent Control Header ----------------------------------------------------------------- Extent Header:: spare1: 0 space2: 0 #extents: 1 #blocks: 4 last map 0x00000000 #maps: 0 offset: 4128 Highwater:: 0x02c00004 ext#: 0 blk#: 1 ext size: 4 #blocks in seg. hdr's freelists: 1 #blocks below: 1 mapblk 0x00000000 offset: 0 Unlocked Map Header:: next 0x00000000 #extents: 1 obj#: 25755 flag: 0x40000000 Extent Map ----------------------------------------------------------------- 0x02c00003 length: 4 nfl = 1, nfb = 1 typ = 1 nxf = 0 SEG LST:: flg: USED lhd: 0x02c00003 ltl: 0x02c00003 End dump data blocks tsn: 8 file#: 11 minblk 2 maxblk 2 ―――――――――――――――――――――――――――――――――― 这里我们看到表空间号是tsn: 8,数据文件号是file#: 11,相对数据块地址是rdba: 0x02c00002 (11/2),SCN为scn: 0x0000.001148eb(SCN Base=0011,SCN Wrap=48eb),尾区版本号为tail: 0x48eb1001(tail=SCN Wrap: 48eb + type: 0x10+ seq: 0x01),由于这个块是整个Segment的头,所以它还包含整个Segment的一些存储信息,比如extent数,block数,高水位地址Highwater:: 0x02c00004,自由列表信息hdr's freelists: 1等等。假如才用本地治理表空间,则此块的存储信息通过位图方式治理。 真正的数据是储存在下一个块也就是0x02c00002+1=0x02c00003,我们来看看究竟。 ―――――――――――――――――――――――――――――――――― *** 2003-06-12 12:00:41.781 Start dump data blocks tsn: 8 file#: 11 minblk 3 maxblk 3 buffer tsn: 8 rdba: 0x02c00003 (11/3) scn: 0x0000.001148ee seq: 0x01 flg: 0x02 tail: 0x48ee0601 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data Block header dump: 0x02c00003 Object id on Block? Y seg/obj: 0x649b csc: 0x00.1148eb itc: 1 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 xid: 0x0006.03f.000000da uba: 0x00800ad2.00ae.04 --U- 2 fsc 0x0000.001148ee data_block_dump =============== tsiz: 0x1fb8 hsiz: 0x16 pbl: 0x0ec77444 bdba: 0x02c00003 flag=----------- ntab=1 nrow=2 frre=-1 fsbo=0x16 fseo=0x1fac avsp=0x1f90 tosp=0x1f90 0xe:pti[0] nrow=2 offs=0 0x12:pri[0] offs=0x1fb2 0x14:pri[1] offs=0x1fac block_row_dump: tab 0, row 0, @0x1fb2 tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 02 tab 0, row 1, @0x1fac tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 03 end_of_block_dump End dump data blocks tsn: 8 file#: 11 minblk 3 maxblk 3 ―――――――――――――――――――――――――――――――――― 谜团解开了,ITL,数据都呈现出来了,开始分析! Block header dump: 0x02c00003 Object id on Block? Y seg/obj: 0x649b csc: 0x00.1148eb itc: 1 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 数据块地址正是0x02c00002+1=0x02c00003 segment/object id为0x649b,转成10进制为25755,可以由obj#表中得知 SQL> select obj# from sys.obj$ where name='TESTBLOCK'; OBJ# ---------- 25755 csc(SCN at last Block CleanOut): 0x00.1148eb表示最后一次块清除(Block CleanOut)时候的SCN,关于块清除的概念可以查阅Thomas Kyte 著的”eXPert one by one Oracle”。
itc: 1 表示Number of itl slots flg: O 表示此块被放置在自由列表(freelist)中 typ: 1 – DATA,类型1表示数据,类
|