轉帖vage http://www.itpub.net/thread-1597605-1-1.html 收藏學習
第一章 ASM文件
ASM中的文件總體上來說,分為兩大類,元文件和數據文件。數據文件包含Oracle的數據文件、控制文件、重做日志文件、歸檔日志文件等等。對於ASM來說,只要是非元文件,就是數據文件。
每一個文件,在ASM中都有一個專門的索引號,也就是編號,ASM文件索引號從1開始。其中,前255個,也就是1至255號文件,都是元文件。256之后的是其他各種文件。
元文件中包含了各種ASM的配置、各類數據文件信息還有目錄、別名等等信息,都是在元文件中的。所有V$ASM_開頭視圖的信息,都來自元文件中。
其中,1號文件包含所有文件的磁盤占用信息,包括元文件、甚至1號文件自身的空間分布信息,也都是在1號文件內部。每個文件在它里面占用一個塊(4096字節,元數據塊大小為4K)的空間。
從256號文件開始,是數據庫的各類文件。假設你放在ASM上的第一個文件是一個控制文件A,第二個文件是一個數據文件B。哪么控制文件A在ASM中的索引號是256,數據文件B的索引號是257。
1號文件總是開始在0號磁盤2號AU,記住這個位置:0號盤2號AU。這是ASM中定位文件的起點,它的作用,有點相當於磁盤上的引導區,在電腦開機后負責將OS啟動起來。
1號文件在最少情況下,至少有兩個AU。上面我們提到過了,在1號文件中,每個文件占用一個元數據塊,存放自身的空間分布信息。每個元數據塊大小是4K,一個AU是1M,哪么,每個AU中,可以存儲256個文件的空間分布信息。這其中,0號盤2號AU中,全是元文件的信息。再具體一點,0號盤2號AU,第一個元數據塊被系統占用,從第二個塊開始,到255為止,共255個元數據塊,對應索引號1至255的文件。其實,也就是全部的元文件了。也就是說0號盤2號AU,保存了全部元文件的空間分布信息。
1號文件的第二個AU,從第一個塊開始,保存256號文件。第二個塊對應257號文件,等等。
每次從ASM中讀數據時,Oracle都要先讀到1號文件,從中找出要讀的目標文件在磁盤上的分布位置,然后再去讀取相應的文件的數據。
不用太多文字了,文字不是最直接的表達方式,還是換成圖形吧。
<IGNORE_JS_OP>
圖1
這張圖假設某一DiskGroup中有0到N個磁盤。再看下圖:
<IGNORE_JS_OP>
圖2
我們把0號盤,2號AU單獨拿出來,放大顯示。0號盤2號AU,是1號文件第一個AU,共有256個元數據塊,編號0至255,0號塊留用。1至255號塊分別保存了1號文件自身和2、3等等直到255號文件的AU分布信息。
哪下面,如果我想知道某一個文件的AU分布,如何查看呢?
第 二 章 kfed
1、鏈接kfed
查看ASM磁盤的信息,可以使用KFED,在非Windows操作系統下,kfed已經編譯過了,只要鏈接一下,就可以使用了,步驟如下:
(1)、找到ins_rdbms.mk所在路徑,並進入。此步驟不再列出。
(2)、執行如下命令,即可鏈接kfed。
make -f ins_rdbms.mk ikfed
2、在ASM中確定磁盤 :
SQL> select group_number,name from v$asm_diskgroup;
GROUP_NUMBER NAME
------------ ------------------------------
1 DG1
我目前只有一個DG,名字是DG1,GROUP_NUMBER為1。
SQL> select group_number,disk_number,path from v$asm_disk;
GROUP_NUMBER DISK_NUMBER PATH
------------ ----------- --------------------
1 0 ORCL:VOL1
1 1 ORCL:VOL2
目前,我DG中,有兩個磁盤。但這兩個磁盤分別是誰,從ASM的視圖中,還看不出來。不過,可以分析一下得出,/dev/sda這個盤,是系統留用的,sdb、sdc很有可能是ASM的VOL1、VOL2。那么,如何確認一下呢?這里,我也沒有什么好方法,我們這樣:
[root@red1 dev]# dd if=/dev/sdb bs=1 count=45|hexdump -c|more
45+0 records in
45+0 records out
0000000 001 202 001 001 \0 \0 \0 \0 \0 \0 \0 200 , , m
0000010 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 O R C L D I S K V O L 1 \0
000002d
我dd命令,將/dev/sdb的前45個字節輸出,其中,我們可以看到O R C L D I S K V O L 1。那么,/dev/sdb就對應VOL1了。
使用同樣的方法,可以確定sdc是VOL2。還可以確定,磁盤沒有分區:
[root@red1 dev]# dd if=/dev/sdb1 bs=1 count=45|hexdump -c
dd: opening `/dev/sdb1': No such file or directory
不存在/dev/sdb1這樣的設備。
這種確定方法確實麻煩了一些,大家如果知道有什么簡單方法可以補充。
好,我們已經確定,/dev/sdb對應VOL1,是磁盤0,/dev/sdc對應VOL2,是磁盤1。在我們使用kfed時,還用不到這個,如果用程序直接讀取ASM文件的話,就需要用到這個信息了。
3、使用Kfed
我們使用Kfed直接讀取0號磁盤,2號AU,1號元數據塊吧。
0號元數據塊是1號文件自身留作文件頭的。1號元數據塊呢,是1號文件的AU分布,2號元數據塊,是2號文件的AU分布。等等。下面,我們用Kfed讀取下1號元數據塊。
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=2 blkn=1|more
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 4 ; 0x002: KFBTYP_FILEDIR
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 1 ; 0x004: T=0 NUMB=0x1
kfbh.block.obj: 1 ; 0x008: TYPE=0x0 NUMB=0x1
kfbh.check: 4143342569 ; 0x00c: 0xf6f663e9
kfbh.fcn.base: 268 ; 0x010: 0x0000010c
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
…………………………………………………………………………
等等
Kfed可以幫我們列出很多信息,有了這些,ASM的大部分秘密將被揭開。kfed的信息是這樣看的,比如:
kfbh.endian: 1 ; 0x000: 0x01
kfbh.endian是C語言的結構(struct)中的域。
1 ; 0x000: 0x01 :kfbh.endian的十進值為1,0x000是指它開始自第0個字節處,最后的0x01是十六進制值形式。
此域的意義是主機的大小端。0是大端,1是小端。此處值為1,說明主機是小端。
其他的這里就不再一一列出了,對其中的每個域,我后面有詳細的說明。下面,只說相關的,在Kfed中找到如下信息:
kfffde[0].xptr.au: 2 ; 0x4a0: 0x00000002
kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0
kfffde[0].xptr.chk: 40 ; 0x4a7: 0x28
kfffde[1].xptr.au: 27 ; 0x4a8: 0x0000001b
kfffde[1].xptr.disk: 0 ; 0x4ac: 0x0000
kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 C=0 S=0
kfffde[1].xptr.chk: 49 ; 0x4af: 0x31
kfffde[2].xptr.au: 4294967295 ; 0x4b0: 0xffffffff
kfffde[2].xptr.disk: 65535 ; 0x4b4: 0xffff
kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=0 C=0 S=0
kfffde[2].xptr.chk: 42 ; 0x4b7: 0x2a
kfffde[3].xptr.au: 4294967295 ; 0x4b8: 0xffffffff
kfffde[3].xptr.disk: 65535 ; 0x4bc: 0xffff
kfffde[3].xptr.flags: 0 ; 0x4be: L=0 E=0 D=0 C=0 S=0
kfffde[3].xptr.chk: 42 ; 0x4bf: 0x2a
………………
如果你對C語言熟一點,我們會更容易描述這段信息,如果不太熟又想深入了解,可以回去翻翻譚浩強C語言書中結構體哪一部分,很簡單的。kfffde,是結構數組。kfffde[0]的數據元素,存放了1號文件第一個AU的位置。kfffde[1]存放了1號文件第二個AU位置,等等,依次類推。我們來看一下上面的信息:
kfffde[0].xptr.au: 2 ; 0x4a0: 0x00000002 :2號AU
kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000 :0號磁盤
:上兩個信息合起來,0號盤2號AU,這就是1號文件第一個AU的位置
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0 :標志位
kfffde[0].xptr.chk: 40 ; 0x4a7: 0x28 : 校驗碼
通過上面kfffde[0]中的信息,我們可以知道,1號文件的第一個AU,位置在0號盤2號AU處。再看kfffde[1],它對應1號文件第二個AU,位置在0號盤27號AU。再往下看kfffde[3],AU編號4294967295,磁盤編號65535。這說明1號文件還沒有第三個AU。
通過上面的信息,我們可以得到,1號文件共有兩個AU,分別在0號盤2號AU、0號盤27號AU。
再來一張圖,幫助理解:
<IGNORE_JS_OP>
圖3
4、讀取其他文件:讀取元文件
再來一個例子,假設我們想要訪問3號文件,如何找出3號文件的AU都在哪里分布呢?
根據我們剛才所講的,3號文件的AU分布,在(0號盤,2號AU,3號塊)中,使用Kfed讀取它:
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=2 blkn=3|more
…………………………
kfffde[0].xptr.au: 3 ; 0x4a0: 0x00000003
kfffde[0].xptr.disk: 1 ; 0x4a4: 0x0001
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0
kfffde[0].xptr.chk: 40 ; 0x4a7: 0x28
kfffde[1].xptr.au: 3 ; 0x4a8: 0x00000003
kfffde[1].xptr.disk: 0 ; 0x4ac: 0x0000
kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 C=0 S=0
kfffde[1].xptr.chk: 41 ; 0x4af: 0x29
kfffde[2].xptr.au: 4 ; 0x4b0: 0x00000004
kfffde[2].xptr.disk: 1 ; 0x4b4: 0x0001
kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=0 C=0 S=0
kfffde[2].xptr.chk: 47 ; 0x4b7: 0x2f
kfffde[3].xptr.au: 4 ; 0x4b8: 0x00000004
kfffde[3].xptr.disk: 0 ; 0x4bc: 0x0000
kfffde[3].xptr.flags: 0 ; 0x4be: L=0 E=0 D=0 C=0 S=0
kfffde[3].xptr.chk: 46 ; 0x4bf: 0x2e
………………………………………………
根據我們前面我講的,解讀這些信息是很容易的。3號文件的AU有:(1號盤3號AU)、(0號盤3號AU)、(1號盤4號AU)、(0號盤4號AU)、…………。
還是來看張圖吧,更加清楚些:
<IGNORE_JS_OP>
圖4
5、讀取數據文件
我先在ASM中新建一個數據文件,然后,我們再來查看它的AU分布。
創建如下表空間:
create tablespace tbs_tst01 datafile '+DG1/data/tbs_tst01_00.dbf' size 10M autoextend off;
我們創建了一個10M大的數據文件,也就是說,它會有10個AU。如下查詢一下它在ASM中的文件索引號:
(在ASM實例中執行如下語句:)
SQL> select name,file_number from v$asm_alias where name like 'tbs_tst01%';
NAME FILE_NUMBER
------------------------------------------------ -----------
tbs_tst01_00.dbf 257
FILE_NUMBER列也是文件號,我們一般稱它為ASM文件索引號,在這里 tbs_tst01_00.dbf的索引號是 257。
1號文件的第一個AU(0號盤2號AU)中,只能保存1至255號文件的。從256號文件開始,AU的分布信息保存在1號文件第二個AU中,也就是(0號盤,27號AU)。其中第一個塊(0號塊),對應256號文件。1號塊對應257號文件,等等,依此類推。
照慣例,我們先用Kfed讀取一下0號盤27號AU的1號塊,查看一下257號文件的AU分布:
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=27 blkn=1|more
…………………………………………
kfffde[0].xptr.au: 278 ; 0x4a0: 0x00000116
kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0
kfffde[0].xptr.chk: 61 ; 0x4a7: 0x3d
kfffde[1].xptr.au: 277 ; 0x4a8: 0x00000115
kfffde[1].xptr.disk: 1 ; 0x4ac: 0x0001
kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 C=0 S=0
kfffde[1].xptr.chk: 63 ; 0x4af: 0x3f
kfffde[2].xptr.au: 279 ; 0x4b0: 0x00000117
kfffde[2].xptr.disk: 0 ; 0x4b4: 0x0000
kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=0 C=0 S=0
kfffde[2].xptr.chk: 60 ; 0x4b7: 0x3c
…………………………………………
…………………………………………
…………………………………………
kfffde[10].xptr.au: 283 ; 0x4f0: 0x0000011b
kfffde[10].xptr.disk: 0 ; 0x4f4: 0x0000
kfffde[10].xptr.flags: 0 ; 0x4f6: L=0 E=0 D=0 C=0 S=0
kfffde[10].xptr.chk: 48 ; 0x4f7: 0x30
kfffde[11].xptr.au: 4294967295 ; 0x4f8: 0xffffffff
kfffde[11].xptr.disk: 65535 ; 0x4fc: 0xffff
kfffde[11].xptr.flags: 0 ; 0x4fe: L=0 E=0 D=0 C=0 S=0
kfffde[11].xptr.chk: 42 ; 0x4ff: 0x2a
257號文件一共10個AU,所以,kfffde[11]中的AU位置和磁盤位置是0xffffffff、0xffff。但kfffde[10]還有是明確的值的。257號文件的10號AU位置:0號磁盤283號AU,這其實是257的第11個AU。
tbs_tst01表空間使用的是“系統管理區大小”,也就是說區大小有64K、1M、8M等多種選擇。但是無論區大小,每個ASM中的文件,比原大小總會多出一個AU。就像這里的257號文件,原大小是10M,但實際是11M,共11個AU。
再來一張圖吧,有圖清楚些:
<IGNORE_JS_OP>
圖5
<IGNORE_JS_OP>
圖6
上面圖5和圖6,具體描述了在ASM中讀取257號文件的步驟。在這里,257號文件創建大小是10M,實際在ASM中大小為11M,共11個AU。這11個AU的信息,都在0號盤、27號AU、1號塊中。假設有一個非常大的文件,AU數也非常多,一個塊中存不完,Oracle是如何處理的呢?下面,我們繼續。
6、讀取特別大的文件:間接AU
創建一個稍大一點的數據文件,比如200M:
create tablespace tbs_tst02 datafile '+DG1/data/tbs_tst02_00.dbf' size 200M autoextend off;
根據我們前面所講的,200M的數據文件,在ASM中實際將占用201M空間(201個AU)。下面,我們查找一下此文件的AU分布。首先在ASM中執行如下命令:
SQL> select name,file_number from v$asm_alias where name like 'tbs_tst02%';
NAME FILE_NUMBER
------------------------------------------------ -----------
tbs_tst02_00.dbf 258
確定一下,tbs_tst02_00.dbf的文件號是258。它的AU分布信息,應該在1號文件的第二個AU的第3個塊(2號塊)中,老規距,先用Kfed讀取1號文件第二個AU第3個塊,也就是0號盤、27號AU、2號塊:
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=27 blkn=2|more
………………………………………………………………
kfffde[0].xptr.au: 282 ; 0x4a0: 0x0000011a
kfffde[0].xptr.disk: 1 ; 0x4a4: 0x0001
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0
kfffde[0].xptr.chk: 48 ; 0x4a7: 0x30
kfffde[1].xptr.au: 284 ; 0x4a8: 0x0000011c
kfffde[1].xptr.disk: 0 ; 0x4ac: 0x0000
kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 C=0 S=0
kfffde[1].xptr.chk: 55 ; 0x4af: 0x37
………………………………………………………………
這些信息我們都熟悉了,是說明258號文件的AU分布,第一個AU在1號盤、282號AU處。第二個AU是0號盤、284號AU。等等。一直向下翻頁,你會發現在kfffde[61]處,AU信息和Disk信息就已經沒有了。kfffde[60]是最后一個有效AU,位置是0號盤、314號AU處:
………………………………………………………………
kfffde[60].xptr.au: 314 ; 0x680: 0x0000013a
kfffde[60].xptr.disk: 0 ; 0x684: 0x0000
kfffde[60].xptr.flags: 0 ; 0x686: L=0 E=0 D=0 C=0 S=0
kfffde[60].xptr.chk: 17 ; 0x687: 0x11
kfffde[61].xptr.au: 4294967295 ; 0x688: 0xffffffff
kfffde[61].xptr.disk: 65535 ; 0x68c: 0xffff
kfffde[61].xptr.flags: 0 ; 0x68e: L=0 E=0 D=0 C=0 S=0
kfffde[61].xptr.chk: 42 ; 0x68f: 0x2a
………………………………………………………………
其實,kfffde[60]已經不是258號文件實際存放數據的AU了,直到kfffde[59]還是。也就是說kfffde[0]到kfffde[59],第258號文件的前60個AU的位置信息(也就是前60M了),保存在此處。258號文件共201個AU呢,后面141個AU的位置信息在哪兒呢?就在kfffde[60]對應的,0號盤、314號AU中。
再來讀取一下它:0號盤、314號AU。
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=314 blkn=0|more
………………………………………………………………
kfbh.block.obj: 258 ; 0x008: TYPE=0x0 NUMB=0x102
………………………………………………………………
kffixe[0].xptr.au: 312 ; 0x00c: 0x00000138
kffixe[0].xptr.disk: 1 ; 0x010: 0x0001
kffixe[0].xptr.flags: 0 ; 0x012: L=0 E=0 D=0 C=0 S=0
kffixe[0].xptr.chk: 18 ; 0x013: 0x12
kffixe[1].xptr.au: 315 ; 0x014: 0x0000013b
kffixe[1].xptr.disk: 0 ; 0x018: 0x0000
kffixe[1].xptr.flags: 0 ; 0x01a: L=0 E=0 D=0 C=0 S=0
kffixe[1].xptr.chk: 16 ; 0x01b: 0x10
kffixe[2].xptr.au: 313 ; 0x01c: 0x00000139
kffixe[2].xptr.disk: 1 ; 0x020: 0x0001
kffixe[2].xptr.flags: 0 ; 0x022: L=0 E=0 D=0 C=0 S=0
kffixe[2].xptr.chk: 19 ; 0x023: 0x13
………………………………………………………………
我多顯示了一個域的信息:kfbh.block.obj,它代表此數據塊屬於哪個文件,此處的值為258,代表此數據塊、此AU屬於258號文件。
kffixe[0]是258號文件的第61個AU,它的位置是1號盤312號AU。注意,它就是一個間接AU。后面的kffixe[1]、kffixe[2],……,等等也都是間接AU了。
好,258號文件AU分布的查找過程,我用三幅圖總結:
<IGNORE_JS_OP>
圖7
<IGNORE_JS_OP>
圖8
<IGNORE_JS_OP>
圖9
ASM文件管理模式到這里就差不多了。我們使用Kfed,直接讀取磁盤,描述了查找、定位文件AU分布的方式。如果只是想看看某個文件的AU分布,當然不用每次都使用Kfed,我們可以在ASM實例中,查詢X$KFFXP視圖。
第 三 章X$KFFXP
這個視圖很容易理解,我把它的主要列介紹一下:
GROUP_KFFXP :磁盤組編號
NUMBER_KFFXP :文件編號
PXN_KFFXP :物理區號
XNUM_KFFXP :邏輯區號
LXN_KFFXP :0=primary, 1=first mirror, 2=second mirror
DISK_KFFXP :磁盤編號
AU_KFFXP :AU號
通常,一個AU就是一個區。邏輯區和物理區的區別是,如果冗余模式是Nomarl,有兩個FailGroup,那么文件的每一個AU,可以稱為一個邏輯區。它在兩個FailGroup中分別各自對應一個AU,每個AU稱為物理區。
我想,這個視圖不用我再過多介紹了吧。
第四章 ASM文件直接讀取
終於到本文的壓軸戲了,繞過Oracle,直接讀取ASM文件。閱讀本章,你就需要點編程基礎了。程序不長,一共只不過300多行而已。其實如查你仔細閱讀了本文前面的內容,而且也都理解了,那么,你應該感覺到了,自己開發一個這樣的程序並非難事。
如果你曾經是專業的C程序員,看到Kfed的輸出,你應該就感覺到了,它輸出的結果就是Struct。比如AU的位置信息,直接AU的Struct叫kfffde,間接AU叫kffixe,結構都一樣,可以如下定義:
typedef struct XPTR
{
unsigned int au;
unsigned short int disk;
unsigned char flags;
unsigned char chk;
}XPTR;
XPTR *kfffde,* kffixe;
這個結構會占用8個字節,一個4096字節的塊,是可以保存很多AU的。但是,不知出於什么原因,每個文件的AU位置信息在1號文件所占用的第一個塊中,只保存前60個AU的位置,編號分別為0至59。這60個AU就是前文中提到的直接AU了。而第61個AU(編號為60),保存文件其他AU的位置分布信息,其他的AU就是間接AU了。
我們只需要參照Kfed的輸出結果,定義各種Struct,然后根據直接Open磁盤設備文件,將信息讀入各種Struct就行了。
哪么,還有一個難點,如何解讀Kfed的輸出結果?沒關系,我已經考慮到這個問題了,各種Struct的解讀,我已經放在本文的后幾章。
程序非常簡單,我不再過多說明,有問題可以給我留言,請記住我的永久域名:www.MythData.com。
如果哪個公司有進一步完善、開發成產品的需求,只要有錢賺都可以聯系我,大家一起合作、一起發財。
不過,說實話,仔細看看我這篇文章,再做做測試,找個廉價的C程序員(剛過二級考試哪種),就能把這個程序寫出來,其實根據不需要找我的。
下面測試一下程序,將附件中的程序直接編譯:
[root@red1 asm]# gcc -o rdasm rdasm.c
我這里沒有報任何錯,如果你編譯不過去,可以給我留言。下面測試一下:
步1:查看表空間
SQL> select file_name,tablespace_name from dba_data_files where tablespace_name='RDASM';
FILE_NAME TABLESPACE_NAME
-------------------------------------------------- ------------------------------
+DG1/data/rdasm.dbf RDASM
以RDASM表空間唯一的數據文件+DG1/data/rdasm.dbf為例,一會兒把它從ASM中讀出來。
步2:創建檢測表:
SQL> create table test1 (id int,cc varchar2(20)) tablespace rdasm;
Table created.
SQL> insert into test1 select rownum,'abc' from dba_objects;
9904 rows created.
SQL> commit;
Commit complete.
在RDASM中創建一個9904行的表,把+DG1/data/rdasm.dbf文件從ASM中讀出來后,可以再對查詢一下此表的行數,驗證讀取是否成功。
步3:把RDASM表空間脫機:
SQL> alter tablespace rdasm offline;
Tablespace altered.
也可以把表空間設置為熱備狀態。
步4:查詢在ASM中此數據文件的編號:
[oracle@red1 ~]$ export ORACLE_SID=myasm
[oracle@red1 ~]$ sqlplus / as sysdba
SQL> select name,file_number from v$asm_alias where name='rdasm.dbf';
NAME FILE_NUMBER
------------------------------------------------ -----------
rdasm.dbf 304
在ASM中,rdasm.dbf的編號為304。
步5:將ASM中的304號文件讀取到/home/oracle/304.dbf中:
[root@red1 drasm]# ./rdasm 304 /home/oracle/304.dbf
目前我的程序只支持根據文件編號讀取。更進一步的,可以只提供文件名,這個功能還沒有實現。
步6:改變一下讀出文件的屬主:
[root@red1 drasm]# ls -lF /home/oracle/304.dbf
-rw-r----- 1 root root 6299648 Oct 19 09:44 /home/oracle/304.dbf
[root@red1 drasm]# chown oracle.oinstall /home/oracle/304.dbf
步7:在數據庫中改名:
SQL> alter database rename file '+DG1/data/rdasm.dbf' to '/home/oracle/304.dbf';
Database altered.
將+DG1/data/rdasm.dbf改為/home/oracle/304.dbf 。
步8:恢復、並聯機表空間
SQL> alter tablespace rdasm online;
alter tablespace rdasm online
*
ERROR at line 1:
ORA-01113: file 18 needs media recovery
ORA-01110: data file 18: '/home/oracle/304.dbf'
把RDASM表空間聯機,雖然報出了錯誤,但並不是文件損壞,而是需要恢復,下面把/home/oracle/304.dbf恢復一下:
SQL> recover datafile 18 ;
ORA-00279: change 431943 generated at 09/15/2009 05:04:28 needed for thread 1
ORA-00289: suggestion : +DG1/archive/1_54_693785914.dbf
ORA-00280: change 431943 for thread 1 is in sequence #54
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
Log applied.
Media recovery complete.
恢復完成后再次聯機RDASM表空間,這次可以成功聯機:
SQL> alter tablespace rdasm online;
Tablespace altered.
步9:測試:
SQL> select count(*) from test1;
COUNT(*)
----------
9904
查詢一下TEST1表,可以正確把9904行讀出來。
第五章 磁盤頭格式
位於每個磁盤第一個AU,AU編號0,可以用如下Kfed命令讀取:
[oracle@red1 disks]$ kfed read /dev/oracleasm/disks/VOL1 aun=0 blkn=0|more
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
……………………
具體內容如下:
00 endian_kfbh:
Little Endian = 1
Big Endian = 0
01 hard_kfbh:
KFBH_HARD 0x02 /* expected magic number */
KFBH_HARD_4K 0x80 /* 4K metadata block size */
KFBH_HARD_8K 0xa0 /* 8K metadata block size */
KFBH_HARD_16K 0xc0 /* 16K metadata block size */
KFBH_HARD_32K 0xe0 /* 32K metadata block size */
02 type_kfbh:
磁盤頭總是KFBTYP_DISKHEAD
03 datfmt_kfbh:
04 to 07 block_kfbh.blk:
磁盤頭總是為0
08 to 0B block_kfbh.obj:
Since this is a little endian architecture this represents the number "0x80000000". The high order byte will always be 0x80 and the lower bytes represent the disk number which is 0x0 here meaning this is the first disk in the diskgroup.
0C to 0F check_kfbh:
校驗碼,寫到磁盤前計算。
10 to 13 fcn_kfbh.base
14 to 17 fcn_kfbh.wrap
18 to 1B fspare1_kfbh
1C to 1f fspare2_kfbh
磁盤頭無意義。
20 to 27 driver_kfdhdb.driver_kfdhdb:
沒有使用Lib包的時候顯示為ORCLDISK。
28 to 3F driver_kfdhdb.reserved_kfddrb:
kfdhdb.driver.reserved[0]: 0 ; 0x008: 0x00000000
kfdhdb.driver.reserved[1]: 0 ; 0x00c: 0x00000000
kfdhdb.driver.reserved[2]: 0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]: 0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]: 0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]: 0 ; 0x01c: 0x00000000
為0。
40 to 43 compat_kfdhdb:
版本號
44 and 45 dsknum_kfdhdb:
可以看到占兩個字節:
kfdhdb.dsknum: 0 ; 0x024: 0x0000
一個DG中,最多只能有65536塊盤。
46 grptyp_kfdhdb:
冗余策略:
KFDGTP_INVALID ((kfdgtp)0) /* Illegal value */
KFDGTP_EXTERNAL ((kfdgtp)1) /* External redundancy */
KFDGTP_NORMAL ((kfdgtp)2) /* Normal redundancy */
KFDGTP_HIGH ((kfdgtp)3) /* High redundancy */
47 hdrsts_kfdhdb:
KFDHDR_INVALID ((kfdhdr)0) /* Illegal value */
KFDHDR_UNKNOWN ((kfdhdr)1) /* Disk header block unreadable */
KFDHDR_CANDIDATE ((kfdhdr)2) /* No OSM or OS disk header found */
KFDHDR_MEMBER ((kfdhdr)3) /* Normal member of the group */
KFDHDR_FORMER ((kfdhdr)4) /* Disk dropped cleanly from group */
KFDHDR_CONFLICT ((kfdhdr)5) /* Header conflicts */
KFDHDR_INCOMPAT ((kfdhdr)6) /* Written by incompatible software*/
KFDHDR_PROVISIONED ((kfdhdr)7) /* Disk was prepared beforehand */
參見V$asm_disk
48 to 67 dskname_kfdhdb
68 to 87 grpname_kfhdb:
88 to A7 fgname_kfdhdb:
A8 to C7 capname_kfdhdb:
未使用
kfdhdb.crestmp.hi: 32956296 ; 0x0a8: HOUR=0x8 DAYS=0x1c MNTH=0x7 YEAR=0x7db
kfdhdb.crestmp.lo: 978288640 ; 0x0ac: USEC=0x0 MSEC=0x3e0 SECS=0x24 MINS=0xe
創建時的時間戳
kfdhdb.mntstmp.hi: 32956352 ; 0x0b0: HOUR=0x0 DAYS=0x1e MNTH=0x7 YEAR=0x7db
kfdhdb.mntstmp.lo: 95641600 ; 0x0b4: USEC=0x0 MSEC=0xd8 SECS=0x1b MINS=0x1
Mount時的時間戳
kfdhdb.secsize: 512 ; 0x0b8: 0x0200
扇區大小
kfdhdb.blksize: 4096 ; 0x0ba: 0x1000
塊大小
kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000
AU大小。
kfdhdb.mfact: 113792 ; 0x0c0: 0x0001bc80
版本相關,無意義
kfdhdb.dsksize: 102 ; 0x0c4: 0x00000066
本磁盤包含的AU數量。kfdhdb.ausize * dsksize_kfdhdb = disk size
kfdhdb.pmcnt: 2 ; 0x0c8: 0x00000002
AU的物理地址空間。
kfdhdb.fstlocn: 1 ; 0x0cc: 0x00000001
說明第一個AU后,是用戶可用空間。
kfdhdb.altlocn: 2 ; 0x0d0: 0x00000002
說明文件目錄開始自第二個AU
kfdhdb.f1b1locn: 2 ; 0x0d4: 0x00000002
File Directory block 1 Allocation Unit number
第六章 PST - Partnership and Status Table
位於每個磁盤第二個AU,AU編號為1。
PST - Partnership and Status Table contains the status information about
the ASM disks in a disk group - disk number, status (either online or offline),
partner disk number, failure group info (11g) and heartbeat info. AU number 1
in every disk within a disk group is reserved for PST. Only a few disk actually
have a PST - in external redundancy group we only have one PST table, in normal
redundancy group (double mirroring) we have up to 3 PST and in high redundancy
we have up to 5 PST. The GMON process is responsible for PST processing. See
kfdp source code for more informaiton.
kfbh.endian
Little endian = 1
Big endian = 0
kfbh.hard
H.A.R.D. magic # and block size
kfbh.type
metadata block type,對PST為KFBTYP_PST_META。
kfbh.datfmt
metadata block data format
kfbh.block
blk :T=0 NUMB=0x100,共四個字節,其中一個字節為T=0,剩余的為NUMB=0x100
obj -- Disk header should have TYPE=0x8 NUMB=<disknumber>
kfbh.check
校驗碼
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
PST最后改變的時間。
kfdpHdrB.time.hi: 32956296 ; 0x000: HOUR=0x8 DAYS=0x1c MNTH=0x7 YEAR=0x7db
kfdpHdrB.time.lo: 978361344 ; 0x004: USEC=0x0 MSEC=0x27 SECS=0x25 MINS=0xe
PST最后被UPDATE的時間
kfdpHdrB.last: 1 ; 0x008: 0x00000001
kfdpHdrB.next: 1 ; 0x00c: 0x00000001
版本號:
kfdpHdrB.copyCnt: 2 ; 0x010: 0x02
1:外部冗余。2:正常冗余。等等
kfdpHdrB.incarn: 0 ; 0x014: 0x00000000
化身號,PST發生移動時增加
kfdpHdrB.copy[0]: 0 ; 0x018: 0x0000
kfdpHdrB.copy[1]: 2 ; 0x01a: 0x0002
kfdpHdrB.copy[2]: 0 ; 0x01c: 0x0000
kfdpHdrB.copy[3]: 0 ; 0x01e: 0x0000
kfdpHdrB.copy[4]: 0 ; 0x020: 0x0000
冗余模式:
[0] -- external redundancy
[0-2] -- normal redundancy
[0-4] -- high redundancy
kfdpHdrB.dtaSz: 4 ; 0x022: 0x0004
kfdpHdrB.dtaSz
kf3.h /* # dta entries in PST */
This is the number of disks that it needs to keep track of.
第七章 目錄結構
磁盤頭中的kfdhdb.f1b1locn位,指明了文件目錄的開始位置。
下面讀取sdd中2號Au的1號塊(第三個Au的第二個塊),1號塊中是1號文件的AU分布。2號塊中是2號文件的AU分布。以此類推。每個塊是4096字節,第一個塊被占作別用,一個AU可以保存255個文件。所以,此DG的0號磁盤、2號AU中保存1至255個文件的AU分布。256號文件在第二個AU中。
$ kfed read /dev/sdd aun=2 blkn=1 | more
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 4 ; 0x002: KFBTYP_FILEDIR // block type = file directory block...
kfffdb.node.incarn: 1 ; 0x000: A=1 NUMM=0x0 // 文件化身號。參見V$ASM_ALIAS.FILE_INCARNATION
kfffdb.node.frlist.number: 4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn: 0 ; 0x008: A=0 NUMM=0x0
kfffdb.hibytes: 0 ; 0x00c: 0x00000000 // 文件大小
kfffdb.lobytes: 2097152 ; 0x010: 0x00200000 // 文件大小(此處是2M,兩個AU)
kfffdb.xtntcnt: 2 ; 0x014: 0x00000002 // 文件一共有兩個區
kfffdb.xtnteof: 2 ; 0x018: 0x00000002 // 在EOF標志前有兩個區
kfffdb.blkSize: 4096 ; 0x01c: 0x00001000 // 標准ASM塊大小
kfffdb.flags: 1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0
// Flag definitions
O - File is original, not snapshot
S - File is striped
S - Strict allocation policy
D - File is damaged
C - File creation is committed
I - File has empty indirect block
R - File has known at-risk value
A - The at-risk value itsefl
kfffdb.fileType: 15 ; 0x021: 0x0f //文件類型為元數據
kfffdb.dXrs: 17 ; 0x022: SCHE=0x1 NUMB=0x1 // 直接區冗余方案
kfffdb.iXrs: 17 ; 0x023: SCHE=0x1 NUMB=0x1 // 間接區冗余方案
kfffdb.dXsiz[0]: 4294967295 ; 0x024: 0xffffffff // # 直接區的大小
kfffdb.dXsiz[1]: 0 ; 0x028: 0x00000000
kfffdb.dXsiz[2]: 0 ; 0x02c: 0x00000000
kfffdb.iXsiz[0]: 4294967295 ; 0x030: 0xffffffff // # 間接區的大小
kfffdb.iXsiz[1]: 0 ; 0x034: 0x00000000
kfffdb.iXsiz[2]: 0 ; 0x038: 0x00000000
kfffdb.xtntblk: 2 ; 0x03c: 0x0002 // 直接區和間接區的總數
kfffdb.break: 300 ; 0x03e: 0x012c // 間接區的索引
kfffdb.priZn: 0 ; 0x040: 0x00 // Primary extent allocation zone
kfffdb.secZn: 0 ; 0x041: 0x00 // Secondary extent allocation zone
kfffdb.ub2spare: 0 ; 0x042: 0x0000 // Spare
kfffdb.alias[0]: 4294967295 ; 0x044: 0xffffffff // No alias pointers for this file
kfffdb.alias[1]: 4294967295 ; 0x048: 0xffffffff
kfffdb.strpwdth: 0 ; 0x04c: 0x00 // Stripe width in extents
kfffdb.strpsz: 0 ; 0x04d: 0x00 // Stripe size in 2^N bytes
kfffdb.usmsz: 0 ; 0x04e: 0x0000 // User metadata size
kfffdb.crets.hi: 32855344 ; 0x050: HOUR=0x10 DAYS=0x9 MNTH=0x5 YEAR=0x7d5
kfffdb.crets.lo: 28766208 ; 0x054: USEC=0x0 MSEC=0x1bc SECS=0x1b MINS=0x0
// 文件的創建日期: 9 May 2005 16:00:27
kfffdb.modts.hi: 32855344 ; 0x058: HOUR=0x10 DAYS=0x9 MNTH=0x5 YEAR=0x7d5
kfffdb.modts.lo: 28766208 ; 0x05c: USEC=0x0 MSEC=0x1bc SECS=0x1b MINS=0x0
// 文件的修改日期
kfffdb.spare[0]: 0 ; 0x060: 0x00000000 // Pad to leave room for 360 kfxp
...
kfffdb.spare[15]: 0 ; 0x09c: 0x00000000
kfffdb.usm: ; 0x0a0: length=0 // User metadata
接下來是1號文件的AU分布
kfffde[0].xptr.au: 2 ; 0x4a0: 0x00000002
kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000
kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 C=0 S=0
kfffde[0].xptr.chk: 40 ; 0x4a7: 0x28
kfffde[1].xptr.au: 92 ; 0x4a8: 0x0000005c
kfffde[1].xptr.disk: 0 ; 0x4ac: 0x0000
kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 C=0 S=0
kfffde[1].xptr.chk: 118 ; 0x4af: 0x76
kfffde[2].xptr.au: 4294967295 ; 0x4b0: 0xffffffff // no more extents
kfffde[2].xptr.disk: 65535 ; 0x4b4: 0xffff
kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=0 C=0 S=0
kfffde[2].xptr.chk: 42 ; 0x4b7: 0x2a
...
第八章 重要的文件
一、1號文件,文件目錄。記錄所有其他文件的AU分布
二、2號文件,磁盤目錄。記錄所有磁盤狀態
其中的標志位信息如下:kfddde[0].state:
#define KFDSTA_INVALID ((kfdsta)0) /* Illegal value */
#define KFDSTA_UNKNOWN ((kfdsta)1) /* ASM disk state not known */
#define KFDSTA_NORMAL ((kfdsta)2) /* Happy disk */
#define KFDSTA_UNUSED ((kfdsta)3) /* Unused State - Open */
#define KFDSTA_DROPPING ((kfdsta)4) /* Disk being dropped from group */
#define KFDSTA_HUNG ((kfdsta)5) /* Disk drop operation hung */
#define KFDSTA_FORCING ((kfdsta)6) /* Disk beinng drop forced */
#define KFDSTA_DROPPED ((kfdsta)7) /* Disk no longer part of group */
#define KFDSTA_ADDING ((kfdsta)8) /* Disk being globally validated */
三、3號文件,ACD
四、4號文件:COD。相當於ASM中的回滾段
五、5號文件:模版目錄
六、別名目錄