數據文件internal的內部結構分析
2024-07-21 02:35:32
供稿:網友
眾所周知,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表示數據,類