ASM的文件结构

经常有朋友问我ASM的文件结构。以便于碰到ASM故障时能够处理。实际上ASM数据的备份是容易被忽视的问题。一旦我们DROP了一个DATABASE或者数据文件,那么在ASM中,包含该文件所有INODE信息的file directory(ASM FILE NUM 1)文件就会被清空。从12C开始,很多朋友都在大规模的使用容器数据库了,在一个CDB下可能包含多个小的PDB,由多个DBA分头管理。如果一不小心误删了一个数据库,要恢复起来,可比以前没有使用ASM的时候复杂的多,这个数据库的所有数据文件的inode信息都会被立即填充为0,只要这一切落盘后,那么如果你想恢复这个数据库的数据就十分困难了。扫描整个ASM磁盘组,然后慢慢拼凑出数据文件是唯一的办法。如果只删除了一个数据库还好办,只有一套数据文件丢失,如果整个ASM磁盘组中多次删除过数据库,那么可能会有很多file_id相同的数据块需要做判断,那就十分复杂了。为了避免这种情况出现,经常备份ALIAS文件(当某个文件删除时,ALIAS文件中的相关项目立即也会被填充为0)、file directory文件,是一种十分好的习惯(不过有这个习惯的用户少之又少)。懂ASM数据结构的朋友可以写一个工具用于备份和恢复alias文件和file directory文件。如果没有这个编程能力的朋友,直接通过asmcmd定期把这个文件备份一下,对于今后出事后恢复数据也是很有帮助的。

ASM是一个十分复杂的体系,不过其文件分配表的结构确是十分简单的。如果有朋友有兴趣写个工具,从ASM中读取文件,也是很容易实现的。ASM通过一系列元数据进行管理。这些元数据类似数据库的数据字典。元数据从形式上分为物理元数据和虚拟元数据。所谓物理元数据,是指记录在磁盘固定位置的数据,主要有:磁盘头、分配表、空闲空间表和伙伴状态表。而虚拟元数据是指以文件的形式存在的元数据,位置不固定,主要有:文件目录、磁盘目录、活动变化目录、继续操作目录、模板目录、别名目录、属性目录、过期目录和注册表等。元数据的每个块为4096字节,每个块都有着相应的结构。

首先我们简单了解一下AU的概念,AU是分配单元,ASM的存储是以AU为单位分配的。10G缺省AU_SIZE是1M,如果要使用非缺省AU_SIZE,需要使用隐含参数。在11G中,这个隐含参数变成了标准参数了。

其次,ASM里的所有数据都是以文件形式组织的。每个文件包含N个AU(除了METADATA文件外)。

首先我们要了解的是DISK HEADER,每个DG的DISK都有一个HEAD,其位置是文件头部(如果以0为第一个块的话,那就是0号块),DISKHEADER其实就是每个DISK的AU 0的BLOCK 0。我们使用kfed来看看:

[grid@localhost ~]$kfed read /dev/oracleasm/disks/ASMDISK1 aun=0

由于篇幅限制,省略了显示结果。

于是我们查看一下AU=2的块:

我们可以看到,这个块的类型是LISTHEAD,这是1号文件(FILEDIR)的文件头。这个文件的块大小是4096,里面保存了文件的分配表的信息。每个文件的分配表占用一个BLOCK(4096字节),1号文件(FILE DIR)的文件分配表在AU 2 BLOCK 1里,我们来看一下:

kfbh.endian: 1 ;0x000: 0x01

kfbh.hard: 130 ; 0x001: 0x82

kfbh.type: 4 ; 0x002: KFBTYP_FILEDIR ----这个块是FILEDIR块

kfbh.datfmt: 1 ; 0x003: 0x01

kfbh.block.blk: 1 ; 0x004: T=0 NUMB=0x1

kfbh.block.obj: 1 ; 0x008: TYPE=0x0 NUMB=0x1 ----1号文件

kfbh.check: 3992216370 ; 0x00c: 0xedf46332

kfbh.fcn.base: 458 ; 0x010: 0x000001ca

kfbh.fcn.wrap: 0 ; 0x014: 0x00000000

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kfffdb.node.incarn: 1 ; 0x000: A=1 NUMM=0x0

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 ------文件大小低字节

kfffdb.xtntcnt: 6 ; 0x014: 0x00000006 ------EXTENT的数量6个(有冗余是3个)

kfffdb.xtnteof: 6 ; 0x018: 0x00000006 ------文件尾部的指针

kfffdb.blkSize: 4096 ; 0x01c: 0x00001000 ---块大小

kfffdb.flags: 1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0

kfffdb.fileType: 15 ; 0x021: 0x0f -----ASM METADATA

kfffdb.dXrs: 19 ; 0x022: SCHE=0x1 NUMB=0x3

kfffdb.iXrs: 19 ; 0x023: SCHE=0x1 NUMB=0x3

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: 6 ; 0x03c: 0x0006

kfffdb.break: 60 ; 0x03e: 0x003c

kfffdb.priZn: 0 ; 0x040: KFDZN_COLD

kfffdb.secZn: 0 ; 0x041: KFDZN_COLD

kfffdb.ub2spare: 0 ; 0x042: 0x0000

kfffdb.alias[0]: 4294967295 ; 0x044: 0xffffffff

kfffdb.alias[1]: 4294967295 ; 0x048: 0xffffffff

kfffdb.strpwdth: 0 ; 0x04c: 0x00

kfffdb.strpsz: 0 ; 0x04d: 0x00

kfffdb.usmsz: 0 ; 0x04e: 0x0000

kfffdb.crets.hi: 32958036 ; 0x050: HOUR=0x14 DAYS=0x12 MNTH=0x9 YEAR=0x7db

kfffdb.crets.lo: 1372204032 ; 0x054: USEC=0x0 MSEC=0x28b SECS=0x1c MINS=0x14

kfffdb.modts.hi: 32958036 ; 0x058: HOUR=0x14 DAYS=0x12 MNTH=0x9 YEAR=0x7db

kfffdb.modts.lo: 1372204032 ; 0x05c: USEC=0x0 MSEC=0x28b SECS=0x1c MINS=0x14

......

......

kfffde[0].xptr.au: 2 ; 0x4a0: 0x00000002 ---AU2是第一个块

kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000

kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 S=0

kfffde[0].xptr.chk: 40 ; 0x4a7: 0x28

kfffde[1].xptr.au: 2 ; 0x4a8: 0x00000002 ----冗余块

kfffde[1].xptr.disk: 1 ; 0x4ac: 0x0001

kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 S=0

kfffde[1].xptr.chk: 41 ; 0x4af: 0x29

kfffde[2].xptr.au: 4294967294 ; 0x4b0: 0xfffffffe --------该项目是空的

kfffde[2].xptr.disk: 65534 ; 0x4b4: 0xfffe

kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=0 S=0

kfffde[2].xptr.chk: 42 ; 0x4b7: 0x2a

kfffde[3].xptr.au: 60 ; 0x4b8: 0x0000003c ----AU 60是第二个块

kfffde[3].xptr.disk: 1 ; 0x4bc: 0x0001

kfffde[3].xptr.flags: 0 ; 0x4be: L=0 E=0 D=0 S=0

kfffde[3].xptr.chk: 23 ; 0x4bf: 0x17

kfffde[4].xptr.au: 60 ; 0x4c0: 0x0000003c ---60块的冗余块

kfffde[4].xptr.disk: 0 ; 0x4c4: 0x0000

kfffde[4].xptr.flags: 0 ; 0x4c6: L=0 E=0 D=0 S=0

kfffde[4].xptr.chk: 22 ; 0x4c7: 0x16

kfffde[5].xptr.au: 4294967294 ; 0x4c8: 0xfffffffe ---空的

kfffde[5].xptr.disk: 65534 ; 0x4cc: 0xfffe

kfffde[5].xptr.flags: 0 ; 0x4ce: L=0 E=0 D=0 S=0

kfffde[5].xptr.chk: 42 ; 0x4cf: 0x2a

kfffde[6].xptr.au: 4294967295 ; 0x4d0: 0xffffffff ----后面全部为空了(EOF是6)

--More--

这个文件的第一个AU(AU 2)中的FILE DIR包含的都是ASM METADATA,文件名从1-255。256以后的数据文件都包含在第二个AU中(AU 60)。在这个数据库中,SYSAUX的ASM文件号是257,因此这个文件的FILEDIR是AU 60的BLOCK 1。

由于篇幅限制,省略了部分内容。DISK 0 ,AU 753是该文件的第一个AU,我们把这个文件DD出来看看是否是这个文件:

这时候我们就可以通过ultraedit去检查下了,可以明显的看到里面有sysaux这个文件名。是不是很简单,不过有些细心的人会有疑问了,一个4096字节的块,只能包含60个AU项,如果有冗余,只能包含30M的AU的指针,超过30M的文件如何处理呢。在每个FILEDIR块中,第61号AU记录是特殊的,其指向的AU不是包含文件数据的AU,而是指向下一个FILEDIR:

我们可以看到这个块的类型是INDIRECT,非直接文件目录。这个AU里包含了余下的AU信息。如果这个AU还放不下这个文件的AU信息,那么最后一条记录指向下一个INDIRECT的AU。

至此大家对ASM文件分配的方法应该有了一个大概的了解了吧。其实了解了这些信息,基本上可以动手写一个从ASM中读取文件的工具了。这里还缺少一个信息,就是文件别名的信息,就是数据文件名和ASM文件号之间的关系。这个别名文件的ASM文件号是6。

[grid@localhost~]$ kfed read /dev/oracleasm/disks/ASMDISK1 aun=2 blkn=6 |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: 6 ; 0x004: T=0 NUMB=0x6

kfbh.block.obj: 1 ; 0x008: TYPE=0x0 NUMB=0x1

kfbh.check: 3972293371 ; 0x00c: 0xecc462fb

kfbh.fcn.base: 0 ; 0x010: 0x00000000

kfbh.fcn.wrap: 0 ; 0x014: 0x00000000

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kfffdb.node.incarn: 1 ; 0x000: A=1 NUMM=0x0

kfffdb.node.frlist.number: 4294967295 ; 0x004: 0xffffffff

kfffdb.node.frlist.incarn: 0 ; 0x008: A=0 NUMM=0x0

kfffdb.hibytes: 0 ; 0x00c: 0x00000000

kfffdb.lobytes: 1048576 ; 0x010: 0x00100000

kfffdb.xtntcnt: 3 ; 0x014: 0x00000003

kfffdb.xtnteof: 3 ; 0x018: 0x00000003

kfffdb.blkSize: 4096 ; 0x01c: 0x00001000

kfffdb.flags: 1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0

kfffdb.fileType: 15 ; 0x021: 0x0f

kfffdb.dXrs: 19 ; 0x022: SCHE=0x1 NUMB=0x3

kfffdb.iXrs: 19 ; 0x023: SCHE=0x1 NUMB=0x3

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: 3 ; 0x03c: 0x0003

kfffdb.break: 60 ; 0x03e: 0x003c

kfffdb.priZn: 0 ; 0x040: KFDZN_COLD

kfffdb.secZn: 0 ; 0x041: KFDZN_COLD

kfffdb.ub2spare: 0 ; 0x042: 0x0000

kfffdb.alias[0]: 4294967295 ; 0x044: 0xffffffff

kfffdb.alias[1]: 4294967295 ; 0x048: 0xffffffff

kfffdb.strpwdth: 0 ; 0x04c: 0x00

kfffdb.strpsz: 0 ; 0x04d: 0x00

kfffdb.usmsz: 0 ; 0x04e: 0x0000

kfffdb.crets.hi: 32958036 ; 0x050: HOUR=0x14 DAYS=0x12 MNTH=0x9 YEAR=0x7db

kfffdb.crets.lo: 1372207104 ; 0x054: USEC=0x0 MSEC=0x28e SECS=0x1c MINS=0x14

kfffdb.modts.hi: 32958036 ; 0x058: HOUR=0x14 DAYS=0x12 MNTH=0x9 YEAR=0x7db

kfffdb.modts.lo: 1372207104 ; 0x05c: USEC=0x0 MSEC=0x28e SECS=0x1c MINS=0x14

kfffdb.dasz[0]: 0 ; 0x060: 0x00

kfffdb.dasz[1]: 0 ; 0x061: 0x00

kfffdb.dasz[2]: 0 ; 0x062: 0x00

kfffdb.dasz[3]: 0 ; 0x063: 0x00

kfffdb.permissn: 0 ; 0x064: 0x00

kfffdb.ub1spar1: 0 ; 0x065: 0x00

kfffdb.ub2spar2: 0 ; 0x066: 0x0000

kfffdb.user.entnum: 0 ; 0x068: 0x0000

kfffdb.user.entinc: 0 ; 0x06a: 0x0000

kfffdb.group.entnum: 0 ; 0x06c: 0x0000

kfffdb.group.entinc: 0 ; 0x06e: 0x0000

kfffdb.usm: ; 0x0a0: length=0

kfffde[0].xptr.au: 49 ; 0x4a0: 0x00000031

kfffde[0].xptr.disk: 0 ; 0x4a4: 0x0000

kfffde[0].xptr.flags: 0 ; 0x4a6: L=0 E=0 D=0 S=0

kfffde[0].xptr.chk: 27 ; 0x4a7: 0x1b

kfffde[1].xptr.au: 49 ; 0x4a8: 0x00000031--ALIAS文件的第一个AU

kfffde[1].xptr.disk: 1 ; 0x4ac: 0x0001

kfffde[1].xptr.flags: 0 ; 0x4ae: L=0 E=0 D=0 S=0

kfffde[1].xptr.chk: 26 ; 0x4af: 0x1a

kfffde[2].xptr.au: 4294967294 ; 0x4b0: 0xfffffffe

kfffde[2].xptr.disk: 65534 ; 0x4b4: 0xfffe

kfffde[2].xptr.flags: 0 ; 0x4b6: L=0 E=0 D=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 S=0

kfffde[3].xptr.chk: 42 ; 0x4bf: 0x2a

kfffde[4].xptr.au: 4294967295 ; 0x4c0: 0xffffffff

kfffde[4].xptr.disk: 65535 ; 0x4c4: 0xffff

kfffde[4].xptr.flags: 0 ; 0x4c6: L=0 E=0 D=0 S=0

kfffde[4].xptr.chk: 42 ; 0x4c7: 0x2a

kfffde[5].xptr.au: 4294967295 ; 0x4c8: 0xffffffff

kfffde[5].xptr.disk: 65535 ; 0x4cc: 0xffff

kfffde[5].xptr.flags: 0 ; 0x4ce: L=0 E=0 D=0 S=0

kfffde[5].xptr.chk: 42 ; 0x4cf: 0x2a

kfffde[6].xptr.au: 4294967295 ; 0x4d0: 0xffffffff

ALIAS文件的第一个AU是49:

[grid@localhost~]$ kfed read /dev/oracleasm/disks/ASMDISK1 aun=49 |more

kfbh.endian: 1 ; 0x000: 0x01

kfbh.hard: 130 ; 0x001: 0x82

kfbh.type: 11 ; 0x002: KFBTYP_ALIASDIR

kfbh.datfmt: 1 ; 0x003: 0x01

kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0

kfbh.block.obj: 6 ; 0x008: TYPE=0x0 NUMB=0x6

kfbh.check: 2830664843 ; 0x00c: 0xa8b8848b

kfbh.fcn.base: 462 ; 0x010: 0x000001ce

kfbh.fcn.wrap: 0 ; 0x014: 0x00000000

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kffdnd.bnode.incarn: 1 ; 0x000: A=1 NUMM=0x0

kffdnd.bnode.frlist.number: 4294967295 ; 0x004: 0xffffffff

kffdnd.bnode.frlist.incarn: 0 ; 0x008: A=0 NUMM=0x0

kffdnd.overfl.number: 4294967295 ;0x00c: 0xffffffff

kffdnd.overfl.incarn: 0 ; 0x010: A=0 NUMM=0x0

kffdnd.parent.number: 0 ; 0x014: 0x00000000

kffdnd.parent.incarn: 1 ; 0x018: A=1 NUMM=0x0

kffdnd.fstblk.number: 0 ; 0x01c: 0x00000000

kffdnd.fstblk.incarn: 1 ; 0x020: A=1 NUMM=0x0

kfade[0].entry.incarn: 1 ; 0x024: A=1 NUMM=0x0

kfade[0].entry.hash: 4004320810; 0x028: 0xeead162a

kfade[0].entry.refer.number: 1 ; 0x02c: 0x00000001

kfade[0].entry.refer.incarn: 1 ; 0x030: A=1 NUMM=0x0

kfade[0].name: ASM ; 0x034: length=3

kfade[0].fnum: 4294967295 ; 0x064: 0xffffffff

kfade[0].finc: 4294967295 ; 0x068: 0xffffffff

kfade[0].flags: 4 ; 0x06c: U=0 S=0 S=1 U=0 F=0

kfade[0].ub1spare: 0 ; 0x06d: 0x00

kfade[0].ub2spare: 0 ; 0x06e: 0x0000

kfade[1].entry.incarn: 1 ; 0x070: A=1 NUMM=0x0

kfade[1].entry.hash: 185602149 ; 0x074: 0x0b101065

kfade[1].entry.refer.number: 3 ; 0x078: 0x00000003

kfade[1].entry.refer.incarn: 1 ; 0x07c: A=1 NUMM=0x0

kfade[1].name: ORCL ; 0x080: length=4

kfade[1].fnum: 4294967295 ; 0x0b0: 0xffffffff

kfade[1].finc: 4294967295 ; 0x0b4: 0xffffffff

kfade[1].flags: 4 ; 0x0b8: U=0 S=0 S=1 U=0 F=0

kfade[1].ub1spare: 0 ; 0x0b9: 0x00

kfade[1].ub2spare: 0 ; 0x0ba: 0x0000

kfade[2].entry.incarn: 0 ; 0x0bc: A=0 NUMM=0x0

kfade[2].entry.hash: 0 ; 0x0c0: 0x00000000

kfade[2].entry.refer.number: 0 ; 0x0c4: 0x00000000

kfade[2].entry.refer.incarn: 0 ; 0x0c8: A=0 NUMM=0x0

kfade[2].name: ; 0x0cc: length=0

kfade[2].fnum: 0 ; 0x0fc: 0x00000000

kfade[51].ub2spare: 0 ; 0xf92: 0x0000

kfade[52].entry.incarn: 0 ; 0xf94: A=0 NUMM=0x0

kfade[52].entry.hash: 0 ; 0xf98: 0x00000000

kfade[52].entry.refer.number: 0; 0xf9c: 0x00000000

kfade[52].entry.refer.incarn: 0; 0xfa0: A=0 NUMM=0x0

kfade[52].name: ; 0xfa4: length=0

kfade[52].fnum: 0 ; 0xfd4: 0x00000000

kfade[52].finc: 0 ; 0xfd8: 0x00000000

kfade[52].flags: 0 ; 0xfdc: U=0 S=0 S=0 U=0 F=0

kfade[52].ub1spare: 0 ; 0xfdd: 0x00

kfade[52].ub2spare: 0 ; 0xfde: 0x0000

这个AU的类型是ALIASDIR,存放别名的,每个AU可以放52个别名,

kfade[0].entry.incarn: 1 ; 0x024: A=1 NUMM=0x0

kfade[0].entry.hash: 2097622492; 0x028: 0x7d072ddc

kfade[0].entry.refer.number: 4294967295 ; 0x02c: 0xffffffff

kfade[0].entry.refer.incarn: 0 ; 0x030: A=0 NUMM=0x0

kfade[0].name: SYSTEM ; 0x034: length=6

kfade[0].fnum: 256 ; 0x064: 0x00000100

kfade[0].finc: 762214281 ; 0x068: 0x2d6e7789

kfade[0].flags: 18 ; 0x06c: U=0 S=1 S=0 U=0 F=1

kfade[0].ub1spare: 0 ; 0x06d: 0x00

kfade[0].ub2spare: 0 ; 0x06e: 0x0000

kfade结构中的fnum就是ASM文件号。

大家应该可以看到,kfade结构中的fnum就是ASM文件号。如果要对ASM的元数据做预防性的备份,那么这个alias文件和前面介绍的file directory文件是必须备份的。还没有采取任何备份措施的朋友,应该考虑做点事情了。

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值