介绍Oracle自带的一些ASM维护工具 (kfod/kfed/amdu)

摘要:
简单的讲ASM是通过一个ASM实例来实现对磁盘的管理。这个和Oracle实例非常类似。依赖于ASM实例的数据库也将不可以訪问ASM磁盘并正常启动。而kfed它能够读取和改动ASM磁盘的元数据,对修复一些关键错误很实用,接下来分别介绍和演示下这两个工具。可是如今我们能够直接通过kfod工具,直接在操作系统层对ASM的相关信息进行查阅,我们先来看下kfod的帮助。

1.前言

ASM(AutomaticStorageManagement)是Oracle主推的一种面向Oracle的存储解决方式,它是一个管理卷组或者文件系统的软件。眼下已经被RAC环境广泛使用,可是ASM因为其高度的封装性,使得我们非常难知道窥探其内部的原理。ASM假设一旦出现故障,通常都非常难处理。

即便在有非常完备的RMAN备份的情况下,恢复起来都可能须要非常长的时间。

简单的讲ASM是通过一个ASM实例来实现对磁盘的管理。这个和Oracle 实例非常类似。

ASM实例也有SGA和后台进程组成。可是ASM实例相对的工作非常少。所以它的SGA 相对较小。其主要维护一些ASM的元数据,包含磁盘组元数据(disk group metadata)、磁盘元数据(disk metadata)、文件元数据(file metadata),ASM的体系结构例如以下图:

介绍Oracle自带的一些ASM维护工具 (kfod/kfed/amdu)第1张

ASM实例管理ASM磁盘组由一个个的ASM磁盘组成,每一个磁盘又由多个区组成,每一个区又由多个AU组成,它们共同协作就构成了ASM的基础应用。

2.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。可是这255个元文件并非都有内容。当中仅仅有前9个文件有内容,我们能够通过訪问x$kffxp内部表获取相关的信息,例如以下:

SQL>SELECT number_kffxp file#, disk_kffxp disk#, COUNT(disk_kffxp) extents

2 FROMx$kffxp

3WHERE group_kffxp=1

4AND disk_kffxp <> 65534

5GROUP BY number_kffxp, disk_kffxp

6ORDER BY 1;

FILE#DISK# EXTENTS

-------------------- ----------

1 0 2

2 0 1

3 0 28

3 3 14

4 0 5

4 3 3

5 0 1

60 1

8 3 1

9 0 1

256 0 482

.........

268 3 7

269 0 1

35 ROWSselected.

file# 1 -file directory

file# 2 -disk directory

file# 3 -active Change Directory(ACD)

file# 4 -continuing Operations Directory (COD)

file# 5 -template directory

file# 6 -alias directory

file# 7 -volume directory

file# 8 -diskUsed Space Directory (USD)

file# 9 -attributes directory

当中1号文件总是開始在0号磁盘2号AU,这是ASM中定位文件的起点。它的作用,有点相当于磁盘上的引导区,在电脑开机后负责将OS启动起来。

每次从ASM中读数据时,Oracle都要先读到1号文件,从中找出要读的目标文件在磁盘上的分布位置,然后再去读取对应的文件的数据。

介绍Oracle自带的一些ASM维护工具 (kfod/kfed/amdu)第2张

那么问题来了,0号AU存放的什么信息呢?这个我想大家已经猜到了。就是存放的ASM磁盘头(disk header)信息,也是我们随后会重点介绍的内容,一旦该磁盘配置好后,假设不再对其做其他的操作,这部分内容相对就固定不变,可是ASM中最为脆弱的又是ASM磁盘头。

假设磁盘头逻辑损坏了。即corrupt了,整个磁盘组将不可以mount。依赖于ASM实例的数据库也将不可以訪问ASM磁盘并正常启动。兴许我们会通过kfed工具对其进行解读。

3.kfod和kfed

kfod和kfed是ASM自带的未公开的工具,kfod主要用于在系统级别对ASM信息的查看。而kfed它能够读取和改动ASM磁盘的元数据,对修复一些关键错误很实用,接下来分别介绍和演示下这两个工具。

下面使用的环境数据库版本号都是11gr2

3.1. kfod介绍

我们曾经要想訪问和查询ASM的信息,仅仅能通过数据库视图进行查询,无法通过操作系统层进行訪问。可是如今我们能够直接通过kfod工具,直接在操作系统层对ASM的相关信息进行查阅,我们先来看下kfod的帮助。输入kfod –h得到结果例如以下:

[oracle@rac01~]$ kfod -h

KFOD-00101:LRM error [107] while parsing command line arguments

_asm_a/llow_only_raw_disks KFOD allow only raw devices[_asm_allow_only_raw_disks=TRUE/(FALSE)]

_asm_l/ibraries ASMLibraries[_asm_libraries=lib1,lib2,...]

_asms/id ASM Instance[_asmsid=sid]

a/sm_diskstring ASM Diskstring[asm_diskstring=discoverystring, discoverystring ...]

c/luster KFOD cluster[cluster=TRUE/(FALSE)]

db/_unique_name db_unique_name for ASMinstance[db_unique_name=dbname]

di/sks Disks to discover[disks=raw,asm,badsize,all]

ds/cvgroup Include group name[dscvgroup=TRUE/(FALSE)]

g/roup Disks in diskgroup[group=diskgroup]

h/ostlist hostlist[hostlist=host1,host2,...]

metadata_a/usize AU Size for Metadata SizeCalculation

metadata_c/lients Client Count for Metadata SizeCalculation

metadata_d/isks Disk Count for Metadata SizeCalculation

metadata_n/odes Node Count for Metadata SizeCalculation

metadata_r/edundancy Redundancy for Metadata SizeCalculation

n/ohdr KFOD header suppression[nohdr=TRUE/(FALSE)]

o/p KFOD options type[OP=DISKS/CANDIDATES/MISSING/GROUPS/INSTS/VERSION/CLIENTS/RM/RMVERS/DFLTDSTR/GPNPDSTR/METADATA/ALL]

p/file ASM parameter file[pfile=parameterfile]

s/tatus Include disk header status[status=TRUE/(FALSE)]

v/erbose KFOD verbose errors[verbose=TRUE/(FALSE)]

我们能够看到。有大量的參数,差点儿能够轻松的查看ASM的全部信息,如我们曾经要查询ASM的磁盘空间大小和剩余量,必须通过登录实例訪问视图,如今就能够直接通过kfod工具查询,例如以下:

l 查看磁盘组信息

[oracle@rac01~]$ kfod di=all op=groups

--------------------------------------------------------------------------------

Group Size Free Redundancy Name

================================================================================

1:16378 Mb 14070 Mb EXTERN DATA

2:509 Mb 459 Mb EXTERN ARCH

l 查看磁盘组的组成

[oracle@rac01~]$ kfod di=all group=diskgroup ds=true

--------------------------------------------------------------------------------

DiskSize Path DiskGroup User Group

================================================================================

1:8189 Mb /dev/asm-disk1 DATA oracle dba

2:8189 Mb /dev/asm-disk2 DATA oracle dba

3:509 Mb /dev/asm-disk3 ARCH oracle dba

3.2. kfed介绍

kfod仅仅是能够通过操作系统直接查看ASM的信息。可是前面我们说了,ASM最易出现故障的不是存储数据的本身,而是ASM磁盘头。那怎样訪问和维护磁盘头呢?这就要用到我们介绍的kfed工具。KFED是ASM自带的一个未公开的工具,它能够对ASM元数据进行一系列的操作,重要的是它能够在ASM无法启动的时候也能够工作,对修复一些关键错误很实用(前面介绍的kfod必须在ASM启动的状态下訪问),我们相同先来看下帮助信息。例如以下:

[oracle@rac01~]$ kfed -h

as/mlib ASM Library [asmlib='lib']

aun/um AU number to examine or update[AUNUM=number]

aus/z Allocation Unit size in bytes[AUSZ=number]

blkn/um Block number to examine or update[BLKNUM=number]

blks/z Metadata block size in bytes[BLKSZ=number]

ch/ksum Update checksum before each write[CHKSUM=YES/NO]

cn/t Count of AUs to process[CNT=number]

de/v ASM device to examine or update[DEV=string]

dm/pall Don't suppress repeated lines whendumping corrupt blocks [DMPALL=YES/NO]

o/p KFED operation type[OP=READ/WRITE/MERGE/REPAIR/NEW/FORM/FIND/STRUCT]

p/rovnm Name for provisioning purposes[PROVNM=string]

s/eek AU number to seek to [SEEK=number]

te/xt File name for translated block text[TEXT=string]

ty/pe ASM metadata block type number[TYPE=number]

kfed能够跳过ASM实例直接訪问磁盘。这就能够在一些很规的环境下,如ASM关闭,磁盘组无法mount等对ASM的相关信息进行訪问,在加上其具备的改动功能,能够利用其对ASM进行修复操作,要想了解kfed的修复方法,我们首先来了解下ASM磁盘头,前面我们通过kfod知道了有/dev/asm-disk1、/dev/asm-disk2、/dev/asm-disk3个磁盘作为ASM的磁盘组所使用。我们又知道,磁盘头的信息存放在每一个磁盘0号AU的位置第0号数据块中,那么如今我们就以当中的一个来看一下它的磁盘头究竟存储了那些信息,例如以下:

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=0 blkn=0

【01】kfbh.endian: 1 ; 0x000: 0x01

【02】kfbh.hard: 130 ; 0x001: 0x82

【03】kfbh.type: 1 ; 0x002:KFBTYP_DISKHEAD

【04】kfbh.datfmt: 1 ; 0x003: 0x01

【05】kfbh.block.blk: 0 ; 0x004: blk=0

【06】kfbh.block.obj: 2147483648 ; 0x008: disk=0

【07】kfbh.check: 875080645 ; 0x00c:0x3428abc5

【08】kfbh.fcn.base: 4892 ; 0x010: 0x0000131c

【09】kfbh.fcn.wrap: 0 ; 0x014: 0x00000000

【10】kfbh.spare1: 0 ; 0x018: 0x00000000

【11】kfbh.spare2: 0 ; 0x01c: 0x00000000

【12】kfdhdb.driver.provstr: ORCLDISK ; 0x000: length=8

【13】kfdhdb.driver.reserved[0]: 0 ; 0x008: 0x00000000

【14】kfdhdb.driver.reserved[1]: 0 ; 0x00c: 0x00000000

【15】kfdhdb.driver.reserved[2]: 0 ; 0x010: 0x00000000

【16】kfdhdb.driver.reserved[3]: 0 ; 0x014: 0x00000000

【17】kfdhdb.driver.reserved[4]: 0 ; 0x018: 0x00000000

【18】kfdhdb.driver.reserved[5]: 0 ; 0x01c: 0x00000000

【19】kfdhdb.compat: 186646528 ; 0x020: 0x0b200000

【20】kfdhdb.dsknum: 0 ; 0x024: 0x0000

【21】kfdhdb.grptyp: 1 ; 0x026:KFDGTP_EXTERNAL

【22】kfdhdb.hdrsts: 3 ; 0x027:KFDHDR_MEMBER

【23】kfdhdb.dskname: DATA_0000 ; 0x028: length=9

【24】kfdhdb.grpname: DATA ; 0x048: length=4

【25】kfdhdb.fgname: DATA_0000 ; 0x068: length=9

【26】kfdhdb.capname: ; 0x088: length=0

【27】kfdhdb.crestmp.hi: 33020845 ; 0x0a8: HOUR=0xdDAYS=0x1d MNTH=0x6 YEAR=0x7df

【28】kfdhdb.crestmp.lo: 1437992960 ; 0x0ac: USEC=0x0MSEC=0x182 SECS=0x1b MINS=0x15

【29】kfdhdb.mntstmp.hi: 33021392 ; 0x0b0: HOUR=0x10DAYS=0xe MNTH=0x7 YEAR=0x7df

【30】kfdhdb.mntstmp.lo: 2467747840 ; 0x0b4: USEC=0x0MSEC=0x1b6 SECS=0x31 MINS=0x24

【31】kfdhdb.secsize: 512 ; 0x0b8: 0x0200

【32】kfdhdb.blksize: 4096 ; 0x0ba: 0x1000

【33】kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000

【34】kfdhdb.mfact: 113792 ; 0x0c0: 0x0001bc80

【35】kfdhdb.dsksize: 8189 ; 0x0c4: 0x00001ffd

【36】kfdhdb.pmcnt: 2 ; 0x0c8: 0x00000002

【37】kfdhdb.fstlocn: 1 ; 0x0cc: 0x00000001

【38】kfdhdb.altlocn: 2 ; 0x0d0: 0x00000002

【39】kfdhdb.f1b1locn: 2 ; 0x0d4: 0x00000002

【40】kfdhdb.redomirrors[0]: 0 ; 0x0d8: 0x0000

【41】kfdhdb.redomirrors[1]: 65535 ; 0x0da: 0xffff

【42】kfdhdb.redomirrors[2]: 65535 ; 0x0dc: 0xffff

【43】kfdhdb.redomirrors[3]: 65535 ; 0x0de: 0xffff

【44】kfdhdb.dbcompat: 168820736 ; 0x0e0: 0x0a100000

【45】kfdhdb.grpstmp.hi: 33020845 ; 0x0e4: HOUR=0xdDAYS=0x1d MNTH=0x6 YEAR=0x7df

【46】kfdhdb.grpstmp.lo: 1437544448 ; 0x0e8: USEC=0x0MSEC=0x3cc SECS=0x1a MINS=0x15

【47】kfdhdb.vfstart: 352 ; 0x0ec: 0x00000160

【48】kfdhdb.vfend: 384 ; 0x0f0: 0x00000180

【49】kfdhdb.spfile: 0 ; 0x0f4: 0x00000000

【50】kfdhdb.spfflg: 0 ; 0x0f8: 0x00000000

【51】kfdhdb.ub4spare[0]: 0 ; 0x0fc: 0x00000000

。。。。

。。(略)

【103】kfdhdb.ub4spare[52]: 0 ; 0x1cc: 0x00000000

【104】kfdhdb.ub4spare[53]: 0 ; 0x1d0: 0x00000000

【105】kfdhdb.acdb.aba.seq: 0 ; 0x1d4: 0x00000000

【106】kfdhdb.acdb.aba.blk: 0 ; 0x1d8: 0x00000000

【107】kfdhdb.acdb.ents: 0 ; 0x1dc: 0x0000

【108】kfdhdb.acdb.ub2spare: 0 ; 0x1de: 0x0000

总共同拥有108行内容,这些内容是什么含义呢?我们来一一解读

第1行:kfbh.endian:小字节(LittleEndian) = 1 大字节(Big Endian) = 0

第2行:kfbh.hard:元文件块大小 默认是0x82

第3行:type_kfbh:类型,磁盘头总是KFBTYP_DISKHEAD

第4行:kfbh.datfmt 数据格式

第5行:kfbh.block.blk磁盘头始终是0

第6行:kfbh.block.obj磁盘在磁盘组中的号

第7行:kfbh.check 校验码,写到磁盘前计算

第8~11行:磁盘头无意义

第12行:kfdhdb.driver.provstr 没有使用Lib包的时候显示为ORCLDISK

第13~18行:kfdhdb.driver.reserved始终为0

第19行:kfdhdb.compat 版本

第20行: kfdhdb.dsknum 0

第21行:kfdhdb.grptyp 冗余策略,共4种冗余策略

KFDGTP_INVALID((kfdgtp)0)/* Illegal value */
KFDGTP_EXTERNAL ((kfdgtp)1)/* Externalredundancy */
KFDGTP_NORMAL ((kfdgtp)2)/*Normal redundancy */
KFDGTP_HIGH ((kfdgtp)3)/* High redundancy */

第22行:hdrsts_kfdhdb 磁盘状态,共8种状态

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 wasprepared beforehand */
參见V$asm_disk
第23行:dskname_kfdhdb 磁盘名称

第24行:grpname_kfhdb 磁盘组名称

第25行:fgname_kfdhdb: 磁盘名称

第26行:capname_kfdhdb 未使用

第27~28行:fdhdb.crestmp.hi。kfdhdb.crestmp.lo创建时的时间戳

第29~30行:kfdhdb.mntstmp.hi,kfdhdb.mntstmp.lo Mount时的时间戳

第31行:kfdhdb.secsize 扇区大小

第32行:kfdhdb.blksize块大小

第33行:kfdhdb.ausize AU大小。

第34行:kfdhdb.mfact: 版本号相关,无意义

第35行:kfhdb.dsksize本磁盘包括的AU数量。kfdhdb.ausize *dsksize_kfdhdb = disk size

第36行:kfdhdb.pmcnt AU的物理地址空间。

第37行:kfdhdb.fstlocn 说明第一个AU后,是用户可用空间。

第37行:kfdhdb.altlocn 说明文件文件夹開始自第二个AU

第38行:kfdhdb.f1b1locn 文件文件夹块1分配单元号

第39~108行:在默认au的情况下,后面的信息基本都变化不大

这部分信息对于ASM识别磁盘很重要,也正式由于它的重要,11g默认就就对其进行了一个镜像备份,能够通过kefd的repair操作直接恢复。相当的方便。

4.ASM磁盘头的修复

因为磁盘头的信息相对简单并且变化非常小,特别是同一磁盘组的磁盘,每一个磁盘头的信息差点儿一致,而当我们了解了磁盘头的信息后,一旦某个磁盘头的信息出现了问题,我们能够利用其它磁盘头信息然后通过kfed工具对其进行改动和调整,达到修复的目的。当中用得最多的是读取(Read)、修复(Repair)和合并(Merge)三个操作。

4.1. Repair修复法

首先大家要明白一点,Oracle正由于知道ASM磁盘头的重要性,因此默认情况下,就对其进行了镜像备份。有点类似于控制文件。在每一个ASM文件的第一个AU位置。是磁盘头信息。而第1个AU位置最后第2个数据块中,默认情况下就是对磁盘头信息的镜像备份。如AU的缺省大小是1M时,那个数据块就是254,我们能够查询下:

磁盘头信息:

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=0 blkn=0|more

kfbh.endian: 1 ; 0x000: 0x01

kfbh.hard: 130 ; 0x001: 0x82

kfbh.type: 1 ; 0x002:KFBTYP_DISKHEAD

kfbh.datfmt: 1 ; 0x003: 0x01

kfbh.block.blk: 0 ; 0x004: blk=0

kfbh.block.obj: 2147483648 ; 0x008: disk=0

kfbh.check: 1997052059 ; 0x00c:0x7708989b

kfbh.fcn.base: 4892 ; 0x010: 0x0000131c

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

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kfdhdb.driver.provstr: ORCLDISK ; 0x000: length=8

kfdhdb.driver.reserved[0]: 0 ; 0x008: 0x00000000

。。。。。(下面内容略)

1号AU倒数第二个数据块信息:

[oracle@rac01~]$ kfed read /dev/asm-disk1aun=1 blkn=254|more

kfbh.endian: 1 ; 0x000: 0x01

kfbh.hard: 130 ; 0x001: 0x82

kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD

kfbh.datfmt: 1 ; 0x003: 0x01

kfbh.block.blk: 254 ; 0x004: blk=254

kfbh.block.obj: 2147483648 ; 0x008: disk=0

kfbh.check: 1997052005 ; 0x00c:0x77089865

kfbh.fcn.base: 4892 ; 0x010: 0x0000131c

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

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kfdhdb.driver.provstr: ORCLDISK ; 0x000: length=8

kfdhdb.driver.reserved[0]: 0 ; 0x008: 0x00000000

。。。。。(下面内容略)

能够看到查询出来的内容相同也是磁盘头内容,这部分是ORACLE自行备份的信息,可是注意该特性仅仅在10.2.0.5及以上版本号才有,10.2.0.4版本号数据库没有这部分信息。

利用dd命令清空当中一个ASM磁盘的磁盘头信息。例如以下

[oracle@rac01~]$ dd if=/dev/zero of=/dev/asm-disk1 bs=4096 count=1

1+0records in

1+0records out

4096bytes (4.1 kB) copied, 0.00157905 s, 2.6 MB/s

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=0blkn=0|more

kfbh.endian: 0 ; 0x000: 0x00

kfbh.hard: 0 ; 0x001: 0x00

kfbh.type: 0 ; 0x002:KFBTYP_INVALID

kfbh.datfmt: 0 ; 0x003: 0x00

kfbh.block.blk: 0 ; 0x004: blk=0

kfbh.block.obj: 0 ; 0x008: file=0

kfbh.check: 0 ; 0x00c:0x00000000

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

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

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

7F8A21E3440000000000 00000000 00000000 00000000[................]

Repeat 255 times

KFED-00322: Invalid contentencountered during block traversal: [kfbtTraverseBlock][Invalid OSM blocktype][][0]

能够看到,/dev/asm-disk1磁盘的磁盘头信息已经被彻底的损坏。我们再查看ASM视图,看下状态;

SQL>select group_Number,DISK_NUMBER,name,HEADER_STATUS,path from v$asm_disk;

GROUP_NUMBERDISK_NUMBER NAME HEADER_STATUS PATH

2 1 DATA_0001 MEMBER /dev/asm-disk2

2 0 DATA_0000 CANDIDATE /dev/asm-disk1

1 0 ARCH_0000 MEMBER /dev/asm-disk3

假设这时候重新启动server,CRS集群也将无法启动,CRS的一些关键信息也是存放在ASM中,曾经遇到这样的情况,我们仅仅能重建ASM,利用备份进行恢复。可是如今我们晓得了磁盘头的备份机制,我们仅仅须要运行一个简单的repair命令,就能够轻松的修复磁盘头信息。例如以下

利用repair命令恢复1号au中的备份信息到0号au磁盘头信息位置。例如以下

[oracle@rac01~]$ kfed repair /dev/asm-disk1

磁盘头的信息被备份信息恢复了,例如以下:

[oracle@rac01~]$ kfed read /dev/asm-disk1

kfbh.endian: 1 ; 0x000: 0x01

kfbh.hard: 130 ; 0x001: 0x82

kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD

kfbh.datfmt: 1 ; 0x003: 0x01

kfbh.block.blk: 0 ; 0x004: blk=0

kfbh.block.obj: 2147483648 ; 0x008: disk=0

kfbh.check: 1997052059 ; 0x00c:0x7708989b

kfbh.fcn.base: 4892 ; 0x010: 0x0000131c

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

kfbh.spare1: 0 ; 0x018: 0x00000000

kfbh.spare2: 0 ; 0x01c: 0x00000000

kfdhdb.driver.provstr: ORCLDISK ; 0x000: length=8

kfdhdb.driver.reserved[0]: 0 ; 0x008: 0x00000000

。。

。。。

。(下面内容略)

4.2. Merge修复法

Repair修复asm磁盘头信息是最简单、最方便的方法,它主要是利用了ORACLE自己主动镜像备份的原因。可是这个功能仅仅在10.2.0.5之后才有,并且假设一旦备份地方(1号AU,倒数第二个块)的信息也被损坏。这个时候就无法利用Repair方式进行恢复了,假设没有备份,那里恢复起来就会比較的麻烦。

可是假设是一个磁盘组的某个磁盘头出现了问题,我们能够结合保存在磁盘中的文件字典(file directory)和(diskdirectory)信息的来进行磁盘头恢复,由于文件字典(filedirectory)。仅仅保存在磁盘组中当中一个磁盘中,这里以/dev/asm-disk1和/dev/asm-disk2为例。由于是同属一个磁盘组,磁盘组名为DATA,例如以下:

[oracle@rac01~]$ kfod di=all group=diskgroup ds=true

--------------------------------------------------------------------------------

DiskSize Path DiskGroup User Group

================================================================================

1: 8189 Mb/dev/asm-disk1DATA oracle dba

2: 8189 Mb/dev/asm-disk2DATA oracle dba

3:509 Mb /dev/asm-disk3 ARCH oracle dba

我们首先来看下。它们两个磁盘,谁是file directory磁盘,通过例如以下查询:

[oracle@rac01~]$ kfed read /dev/asm-disk1 |grep f1b1

kfdhdb.f1b1locn: 2 ; 0x0d4: 0x00000002

[oracle@rac01~]$ kfed read /dev/asm-disk2 |grep f1b1

kfdhdb.f1b1locn: 0 ; 0x0d4: 0x00000000

假设查询出来的结果为非0的,就是file directory磁盘,这里我们能够看到,是/dev/asm-disk1这个磁盘中保存的filecdirectory信息。

1.确认disk directory在磁盘中的位置

[oracle@rac01~]$ kfed read /dev/asm-disk1 |grep f1b1明白file directory的位置,在2au

kfdhdb.f1b1locn: 2; 0x0d4: 0x00000002

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=2 blkn=2 |grep au |head -5明白disk directory的位置

kfffde[0].xptr.au: 3 ; 0x4a0: 0x00000003

kfffde[1].xptr.au: 4294967295 ; 0x4a8: 0xffffffff

kfffde[2].xptr.au: 4294967295 ; 0x4b0: 0xffffffff

kfffde[3].xptr.au: 4294967295 ; 0x4b8: 0xffffffff

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

2.查看磁盘字典信息,由于我们损坏的是/dev/asm-disk2。因此我们这里仅仅关注kfddde[1]的信息,重点关注红色的6条信息。

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=3 blkn=0 |grep name

kfddde[0].dskname: DATA_0000 ; 0x038: length=9

kfddde[0].fgname: DATA_0000 ; 0x058: length=9

kfddde[1].dskname: DATA_0001 ; 0x1f8: length=9

kfddde[1].fgname: DATA_0001 ; 0x218: length=9

kfddde[2].dskname: ; 0x3b8: length=0

kfddde[2].fgname: ; 0x3d8: length=0

。。

。。

(下面内容省略)

这里我们知道DATA磁盘组包括了2个磁盘,当中DATA_0000是本磁盘。那么DATA_0001就是损坏的/dev/asm-disk2磁盘了。因此我们仅仅须要查看涉及该磁盘的相关信息,例如以下:

[oracle@rac01~]$ kfed read /dev/asm-disk1 aun=3 blkn=0 |more

。。。。。。(略)

kfddde[1].entry.incarn: 1 ; 0x1e4: A=1 NUMM=0x0

kfddde[1].entry.hash: 1 ; 0x1e8: 0x00000001

kfddde[1].entry.refer.number:4294967295; 0x1ec: 0xffffffff

kfddde[1].entry.refer.incarn: 0 ; 0x1f0: A=0 NUMM=0x0

kfddde[1].dsknum: 1 ; 0x1f4: 0x0001

kfddde[1].state: 2 ; 0x1f6: KFDSTA_NORMAL

kfddde[1].ddchgfl: 132 ; 0x1f7: 0x84

kfddde[1].dskname: DATA_0001 ; 0x1f8: length=9

kfddde[1].fgname: DATA_0001 ; 0x218: length=9

kfddde[1].crestmp.hi: 33020874 ; 0x238: HOUR=0xa DAYS=0x1eMNTH=0x6 YEAR=0x7df

kfddde[1].crestmp.lo: 574201856 ; 0x23c: USEC=0x0 MSEC=0x268SECS=0x23 MINS=0x8

kfddde[1].failstmp.hi: 0 ; 0x240: HOUR=0x0 DAYS=0x0MNTH=0x0 YEAR=0x0

kfddde[1].failstmp.lo: 0 ; 0x244: USEC=0x0 MSEC=0x0SECS=0x0 MINS=0x0

kfddde[1].timer: 0 ; 0x248: 0x00000000

kfddde[1].size: 8189 ; 0x24c: 0x00001ffd

。。。。。

。(略)

3.依据以上信息,生成/dev/asm-disk2的磁盘头信息(这里能够通过/dev/asm-disk1的磁盘头信息改动)

[oracle@rac01 ~]$ kfed read /dev/asm-disk1aun=0 blkn=0 text=/home/oracle/asm-disk1.txt

利用编辑器打开生成的文件asm-disk1.txt,主要相应改动下面内容

原始的

kfbh.block.obj: 2147483648 ; 0x008: disk=0

kfdhdb.dsknum: 0 ; 0x024: 0x0000

kfdhdb.dskname:DATA_0000 ; 0x028: length=9

kfdhdb.fgname: DATA_0000 ; 0x068: length=9

kfdhdb.crestmp.hi:33020845 ; 0x0a8: HOUR=0xd DAYS=0x1dMNTH=0x6 YEAR=0x7df

kfdhdb.crestmp.lo:1437992960 ; 0x0ac: USEC=0x0 MSEC=0x182 SECS=0x1b MINS=0x15

kfdhdb.dsksize: 8189; 0x0c4: 0x00001ffd

kfdhdb.f1b1locn: 2 ;0x0d4: 0x00000002

改动后的

kfbh.block.obj: 2147483649 ; 0x008: disk=1 (按顺序加1)

kfdhdb.dsknum: 1 ; 0x024: 0x0001 (參照kfddde[1].dsknum

kfdhdb.dskname:DATA_0001 ; 0x028: length=9 (參照kfddde[1].dskname

kfdhdb.fgname: DATA_0001 ; 0x068: length=9 (參照kfddde[1].fgname

kfdhdb.crestmp.hi:33020874; 0x0a8: HOUR=0xd DAYS=0x1d MNTH=0x6 YEAR=0x7df (參照kfddde[1].crestmp.hi

kfdhdb.crestmp.lo:574201856; 0x0ac: USEC=0x0 MSEC=0x182SECS=0x1b MINS=0x15 (參照kfddde[1].crestmp.lo

kfdhdb.dsksize: 8189; 0x0c4: 0x00001ffd (參照kfddde[1].size

kfdhdb.f1b1locn: 0 ;0x0d4: 0x00000000 (由于asm-disk2为非file directory文件)

改动完毕后,保存为新的文本名称为asm-disk2.txt,最后利用merge命令,写入/dev/asm-disk2磁盘头中,例如以下:

[oracle@rac01~]$ kfed merge /dev/asm-disk2 text=/home/oracle/asm-disk2.txt

来总结下利用merge修复的基本步骤。1.首先确认file directory的位置,再依据filedirectory找到dis directory的位置。2.依据disk directory找出磁盘信息,手工编辑磁盘头文件;3最后用kfed merge到相应的磁盘头中。生成磁盘头信息。

最后提一下,普通情况。file directory在磁盘组某个磁盘的au=2的位置,可是假设对磁盘组进行了添加和删除操作。就可能须要手工去查询了。

5.amdu工具使用

前面我们介绍了对磁盘头信息的修复,接下来我们介绍一个对存放在ASM里面的数据进行抽取的工具amdu。我们知道,假设asm实例是启动状态,我们能够通过asmcd或者rman命令将asm中的文件提取出来。可是假设asm无法启动的情况下,以上2个工具就无发实现了。这时候我们就能够用amdu来进行数据文件的抽取。这对于极端情况下的数据恢复是很有帮助的。

AMDU是Oracle 11g里自带的一个免费的工具。用于分析ASM磁盘组的元数据以及从不能mount的磁盘组中往外抽取数据文件,它的原理就是跳过磁盘头直接解析磁盘中的filedirectory部分的内容,然后找到文件和文件夹结构,依据数据文件号,直接将文件抽取出来。

因此,使用AMDU一般要满足下面三个情况:1.ASM实例无法启动。2.磁盘中的filedirectory信息完整;3.知道数据文件号;这样我们就能够尝试把数据文件直接抽取出来,在本地启动数据库实例,接下来我们来操作下。

1.关闭ASM实例

[oracle@rac01~]$ sqlplus /nolog

SQL*Plus:Release 11.2.0.4.0 Production on Thu Jul 23 14:33:24 2015

Copyright(c) 1982, 2013, Oracle. All rightsreserved.

SQL>conn / as sysasm

Connected.

SQL>shutdown immediate;

ASMdiskgroups dismounted

ASMinstance shutdown

因为ASM中存放有CRS相关组件,因此CRS集群也被停止,整个数据库无法訪问,例如以下

[oracle@rac01~]$ crs_stat -t

CRS-0184:Cannot communicate with the CRS daemon.

由于ASM实例没有启动,经常使用的asmcmd也无法訪问相关的信息,例如以下

[oracle@rac01~]$ asmcmd

Connectedto an idle instance.

ASMCMD>ls

ASMCMD-8102:no connection to Oracle ASM; command requires Oracle ASM to run

过去遇到这样的情况,我们仅仅能想方设法的启动ASM实例,不然就仅仅能通过备份文件恢复数据。如今我们能够尝试通过amdu工具,将数据文件直接抽取出来。

2.利用ODU中的asmcmd工具查看数据文件号

因为ORACLE自带的ASMCMD工具无法使用,这时候我们就要借助牛人开发的ODU工具进行查看了,ODU是技术达人开发的一块收费的数据抽取工具(http://www.oracleodu.com/cn/download)。我们仅仅须要下载个试用版,用于查询下即可了。

[oracle@rac01~]$ tar -xvf odu_trial_413_linux_x86.tar

odu/

odu/asmdisk.txt

odu/config.txt

odu/control.txt

odu/data/

odu/odu

解压后,我门仅仅须要对asmdisk.txt这个配置文件进行下设置。仅仅须要设置磁盘号和路径,我们能够通过kfod di=all得到,例如以下;

[oracle@rac01odu]$ kfod di=all

--------------------------------------------------------------------------------

DiskSize Path User Group

================================================================================

1: 8189 Mb/dev/asm-disk1oracle dba

2: 8189 Mb/dev/asm-disk2oracle dba

3: 509 Mb/dev/asm-disk3oracle dba

KFOD-00313:No ASM instances available. CSS group services were successfully initilized bykgxgncin

KFOD-00311:Error scanning device /dev/asm

ORA-15059:invalid device type for ASM disk

Linux-x86_64Error: 16384: Unknown system error

Additionalinformation: 42

[oracle@rac01odu]$ more asmdisk.txt

#disk_no disk_path group_name meta_block_size ausize disk_size header_offset

1/dev/asm-disk1

2 /dev/asm-disk2

3 /dev/asm-disk3

进入odu的asmcmd工具,详细操作例如以下:

[oracle@rac01odu]$ ./odu

OracleData Unloader trial version 4.1.3

Copyright(c) 2008,2009,2010,2011 XiongJun. All rights reserved.

grp#dsk# bsize ausize disksize disknamegroupname path

-------- ----- ------ -------- --------------- -----------------------------------------------------------

10 4096 1024K8189 DATA_0000 DATA /dev/asm-disk1

11 4096 1024K8189 DATA_0001 DATA /dev/asm-disk2

20 4096 1024K509 ARCH_0000 ARCH/dev/asm-disk3

loadasm disk file 'asmdisk.txt' successful

loadingdefault control file ......

ts#fn rfn bsize blocks bf offset filename

-------- ---- ----- -------- -- ------ --------------------------------------------

loadcontrol file 'control.txt' successful

loadingdictionary data......done

loadingscanned data......done

ODU>asmcmd

Enteringasmcmd module.

ASMCMD>ls

Currentdirectory: <root>

DiskGroup

------------------------------------

DATA

ARCH

至此,我们就进入了ODU的ASMCMD工具中,这个工具的命令数据库自带的有所细微的差别。给演示下我们怎样利用它查询数据文件的文件号:

ASMCMD>cd+data

ASMCMD>cd ORCL

Currentdirectory: +DATA/ORCL

ASMCMD>ls

Currentdirectory: +DATA/ORCL/DATAFILE

Name

----------------------------------------

SYSTEM.256.883666707

SYSAUX.257.883666707

UNDOTBS1.258.883666707

USERS.259.883666707

UNDOTBS2.267.883667019

ZLTOOLSTBS.273.884105179

zltoolstbs.dbf =>+DATA.273.884105179

ZL9BASEITEM.274.884105185

zl9baseitem.dbf =>+DATA.274.884105185

ZL9PATIENT.275.884105191

zl9patient.dbf =>+DATA.275.884105191

ZL9EXPENSE.276.884105193

zl9expense.dbf =>+DATA.276.884105193

ZL9MEDLST.277.884105197

zl9medlst.dbf =>+DATA.277.884105197

ZL9DUEREC.278.884105203

zl9duerec.dbf =>+DATA.278.884105203

ZL9CISREC.279.884105207

zl9cisrec.dbf => +DATA.279.884105207

ASM实例中全部文件,都有自己的文件号,如上面每一个文件的后缀中的数字。兴许我们就依据文件号,利用amdu抽取出数据文件。

3.利用amdu抽取数据文件

这里我们尝试控制文件文件抽取出来,让数据库可以启动到mount状态

ASMCMD>cdcontrolfile

Currentdirectory: +DATA/ORCL/CONTROLFILE

ASMCMD>ls

Currentdirectory: +DATA/ORCL/CONTROLFILE

Name

----------------------------------------

Current.261.883666805

Current.260.883666805

这里我们就看到了。控制文件的文件号是260和261。接下来通过amdu进行数据抽取

[oracle@rac01~]$ amdu -diskstring '/dev/asm*' -extract data.260

amdu_2015_07_23_16_15_50/

[oracle@rac01~]$ amdu -diskstring '/dev/asm*' -extract data.261

amdu_2015_07_23_16_16_01/

能够看到,生成了2个目录,进入当中的一个

[oracle@rac01~]$ cd amdu_2015_07_23_16_15_50/

[oracle@rac01amdu_2015_07_23_16_15_50]$ ls

DATA_260.f report.txt

AMDU抽取生成数据文件的格式为“磁盘组+数据文件号”,而且加后缀名为点f,如这里生成的文件就是DATA_260.f,这就是抽取的控制文件,我们能够通过mv对这些文件进行移动并重命名。移动为/u01/app/oracle/controlfile01.ctl例如以下

[oracle@rac01~]$mv /home/oracle/amdu_2015_07_23_16_15_50/DATA_260.f/u01/app/oracle/controlfile01.ctl

接下来我们对系统自带的pfile文件(一般在/u01/app/oracle/admin/orcl/pfile目录中)进行编写,改动里面的控制文件的路径。例如以下

control_files=("+DATA/orcl/controlfile/current.261.883666805","+DATA/orcl/controlfile/current.260.883666805")

cluster_database=true

改动为:

control_files=("/u01/app/oracle/controlfile01.ctl")

cluster_database=false

启动到mount状态

SQL>startup mount pfile='/u01/app/oracle/admin/orcl/pfile/init.ora'

ORACLEinstance started.

TotalSystem Global Area 772472832 bytes

FixedSize 2257232 bytes

VariableSize 566234800 bytes

DatabaseBuffers 201326592 bytes

RedoBuffers 2654208 bytes

Databasemounted.

SQL>

后面我们就能够用类似的方法。通过amdu把其它剩余的全部数据文件、REDO日志文件等抽取出来,然后将控制文件里的路径作调整(能够通过重建控制文件的方式),就是一个简单的冷备恢复,把数据库脱离ASM又一次启动起来,因为篇幅限制这里就不再演示了。

6.总结

ASM作为ORACLE推崇的数据存储方式,在性能、安全、管理上都提供了极大的方便,可是因为其高密闭的封装,导致一旦出现故障。DBA对其往往束手无策。今天我们分别介绍了几个日常大家不怎么接触的数据库自带的ASM维护小工具。可以从内部深探ASM的架构。为我们在极端情况下进行一些解救性的操作提供了方法,请有兴趣的同事可以尝试学习研究,可以有效的掌握这些工具的使用。

參考文档:ASM tools used by Support :KFOD, KFED, AMDU (文档 ID 1485597.1)

免责声明:文章转载自《介绍Oracle自带的一些ASM维护工具 (kfod/kfed/amdu)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇iOS ASA 的归因技术支持_Swiftjs中进行金额计算下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mysql和Oracle在对clob和blob字段的处理

一、MySQL与Oracle数据库如何处理Clob,Blob数据类型 (1)不通数据库中对应clob,blob的类型如下: MySQL中:clob对应text,blob对应blob DB2/Oracle中:clob对应clob,blob对应blob (2)domain中对应的类型: clob对应String,blob对应byte[] clob对应ja...

oracle 中的truncate 和delete

一、查询表大小,块多少语句 Select SEGMENT_Name,BYTES,BLOCKS,Extents From dba_segments Where segment_name In('BAI_NEW_SESSION_HISTORY2') order by segment_name; (2)查表空间 Select Tablespace_Name,...

mysql中的data下的数据文件(.FRM、.MYD、.MYI)恢复为数据

记一次mysql中的data文件操作经历 想拿到一个项目的最新的数据,做功能升级使用,备份一份数据同时也作为本地测试数据,文件有些大,我直接通过远程的phpmyadmin程序导出,不能愉快的玩耍,直接联系了IDC的同事帮忙导一份sql文件出来一下,结果那哥们没得直接扔给了我data文件,这让我如何是好,这个问题我没遇见过啊。处于面子问题,又不好意思再让他重...

Oracle字段

pl/sql查看当前数据库编码语句:select userenv('language') from dual; 测试结果:数据库字符集编码是utf-8 1、nvarchar2(size) ,size不能大于2000;而varchar2(size),size不能大于4000 2、nvarchar2(size)存size个汉字、英文等;varchar2(si...

win10 oracle11g Navicat 连接记录

一. 安装oracle11g服务端 1. 安装参考 https://www.cnblogs.com/liuhongfeng/p/5267549.html 2. 安装好后 oracle默认localhost访问的 需要再进行配置 服务端配置 tnsnames.ora 及 listener.ora 我的目录在 d:/app/Administrator/prod...

oracle sqlplus 命令行中创建存储过程

while 循环插入测试数据 1.创建存储过程 create or replace procedure proc_test_while is i number; begin i := 0; while i < 40 loop i := i + 1; insert...