首页 > 数据库DBA > oracle知识 > oracle存储 >
ASM的文件管理深入解析(内含开源的ASM文件挖掘研究版程序)
09年刚到阿里时,研究过一阵子ASM,当时还写了一个ASM文件直接读取的程序,就是本文后面所附的。算起来,这应该是国内首款这方面的程序了。但当时只发在公司内部的邮件组,一直没有时间整理出来。现在终于清闲些了,而且ASM也使用的越来越多,而且以后绝对是Oracle重点发展方向之一,所以决定将此程序整理出来,再配合些详细的介绍,希望可以提升大家对ASM的了解程度。
也是09年初,曾经和朋友一起写过一个Oracle日志解析的程序,取名为日志挖掘研究版( http://www.itpub.net/thread-1160446-1-1.html,算下来,都已经三年了,时间过的好快啊)。这个ASM直接读取程序,我也决定命令为“ASM文件挖掘研究版”,它还并不完善,只是给有需要的人提供一个思路。如果你不懂编号也没关系,本文的重点,除这个程序外,更多的是介绍ASM文件管理的原理。
“ASM文件挖掘研究版”远没有原来的“日志挖掘研究版复杂,也只花了很短时间,去掉一些调试性的注释只有不到300行代码。
好了,闲言少叙,准备好了吗,开始我们的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号文件,从中找出要读的目标文件在磁盘上的分布位置,然后再去读取相应的文件的数据。
不用太多文字了,文字不是最直接的表达方式,还是换成图形吧。
图1
这张图假设某一DiskGroup中有0到N个磁盘。再看下图:
图2
我们把0号盘,2号AU单独拿出来,放大显示。0号盘2号AU,是1号文件第一个AU,共有256个元数据块,编号0至255,0号块留用。1至255号块分别保存了1号文件自身和2、3等等直到255号文件的AU分布信息。
哪下面,如果我想知道某一个文件的AU分布,如何查看呢?
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。
再来一张图,帮助理解:
图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)、…………。
还是来看张图吧,更加清楚些:
图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。
再来一张图吧,有图清楚些:
图5
图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分布的查找过程,我用三幅图总结:
图7
图8
图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行读出来。
怎么样,简单吧,动心了吧,赶快试一下吧:
|
|