本篇主要介绍asm的1号文件,asm的1号文件是asm的文件目录,它记录了磁盘组中的所有文件信息,由于在asm中,每一个磁盘组都是独立的存储单元,所以每一个磁盘组都会有属于它自己的文件目录。
虽然这是一个内部的文件,但asm实例会把它当做其它asm文件一样管理,在asm的文件目录中也会有它自己的条目(指向了它自己),在一个normal和high冗余的磁盘组中,它也会做镜像,随着新文件的产生,文件目录的大小也会相应地增长。
每一个asm文件目录的条目都会包含如下的信息:
· 文件大小
· 文件块大小
· 文件类型
· 文件的冗余级别
· 文件的条带配置
· 前60个extent的位置指针
· 如果文件超过60个extent,那么会有indirect extent 的指针
· 文件创建时间戳
· 文件最后的修改时间戳
· 指向asm alias目录的文件名
每个新增加的asm文件会分配到一个号码,这个号码是随着新增文件而顺序递增的。文件的号码与文件目录中的block号码也是完全对应的,也就是说,文件目录的1号block描述了他自己也就是1号文件的信息。2号block是描述2号文件的,300号block是描述300号文件的,4000号block是关于4000号文件的,以此类推。如下,是asm的257号文件,kfbh.block.blk指出了文件目录里块的编号,此编号也是文件的编号。
kfed read /dev/qdata/vdf aun=50 blkn=1| grep kfbh.block.blk
kfbh.block.blk: 257 ; 0x004: blk=257
不存在编号为0的asm文件,所以文件目录的0号block不描述任何文件的信息。
asm文件目录与asm的at表是两个相辅相成的数据结构。alter diskgroup check命令可以检查两个数据结构是不是一致的。
译者注:通过为alter diskgroup check语句可以用来校验磁盘组元信息的内部一致性,可以指定在磁盘组、磁盘、文件、failgroup级别进行元信息一致性的校验,能够成功执行此命令的前提条件是磁盘组必须处于mount状态。默认情况下,check disk group 子句会校验所有的元信息目录,在校验过程中如果有错误信息,会记录在asm的alert文件中,check语句一般会执行如下的操作:1)检查磁盘的一致性 2)检查文件extent map和at表之间的一致性 3)检查alias元信息目录和文件目录之间对应关系的正确性 4)检查alias目录树的正确性 5) 检查asm元信息目录是否有不可访问的块。我们可以在语句中添加repair或norepair关键字来指定asm是否尝试修复检查过程中发生的错误,默认为norepair。
asm文件目录中描述的大部分信息都可以通过v$asm_file视图查询到。对于处于mount状态的磁盘组中的每个文件,该视图中会以一行来展示。然而,该视图中并不会显示asm元信息文件的信息。v$asm_file视图中没有描述文件名的列,所以为了得到一个有意义的输出,同时我们还需要联合v$asm_alias视图。
请看如下示例。
sql> select f.group_number, f.file_number, a.name, f.type
from v$asm_file f, v$asm_alias a
where f.group_number=a.group_number and f.file_number=a.file_number
order by 1, 2;
group_number file_number name type
------------ ----------- ---------------------- ----------------
1 253 registry.253.769023761 asmparameterfile
1 256 system.256.769030243 datafile
1 257 sysaux.257.769030245 datafile
1 258 undotbs1.258.769030245 datafile
1 259 users.259.769030245 datafile
1 260 current.260.769030435 controlfile
1 261 current.261.769030431 controlfile
1 262 group_1.262.769030439 onlinelog
1 263 group_1.263.769030445 onlinelog
1 264 group_2.264.769030453 onlinelog
3 256 current.256.771527253 controlfile
3 257 group_1.257.771527259 onlinelog
3 258 group_1.258.771527263 onlinelog
...
34 rows selected.
sql>
不同磁盘组中的文件可以有相同的文件编号。
我们可以在asm实例中通过查询x$kffxp视图来获取磁盘组data中编号为1的文件所分配的au。
sql> select xnum_kffxp "virtual extent",
pxn_kffxp "physical extent",
au_kffxp "allocation unit",
disk_kffxp "disk"
from x$kffxp
where group_kffxp=1 -- diskgroup 1 (data)
and number_kffxp=1 -- file 1 (file directory)
virtual extent physical extent allocation unit disk
-------------- --------------- --------------- ----------
0 0 10 0
0 1 10 1
0 2 10 2
1 3 48 2
1 4 46 1
1 5 47 0
6 rows selected.
以上结果中我们可以有两个发现:asm文件目录为三重冗余(每个virtual extent都有3个physical extent);当前asm文件目录包含两个virtual extent。
当au大小为1mb且asm元信息block大小为4kb时,一个au可以容纳256个目录条目。文件编号1-255是为asm元信息文件预留,所以0号extent只用来容纳元信息文件的条目,1号extent则容纳接下来的256个非元信息文件的信息,以此类推。
译者注:译者认为这里作者遗漏了一个很重要的定位asm一号文件的方法,通过kfed 读取asm磁盘头的kfdhdb.f1b1locn部分,可以获得asm一号文件所在的au,例如下面的例子里显示了一号文件在磁盘的2号au处,如果kfdhdb.f1b1locn的值为0,代表这个磁盘并没有一号文件的拷贝。
#kfed read /dev/qdata/vdh| grep kfdhdb.f1b1locn
kfdhdb.f1b1locn: 2 ; 0x0d4: 0x00000002
接下来我们通过以下查询看看哪些文件是被我的asm实例所管理的。
sql> select file_number "asm file number", name "file name"
from v$asm_alias
where group_number=1
order by 1;
asm file number file name
--------------- ----------------------
253 registry.253.769023761
256 system.256.769030243
257 sysaux.257.769030245
258 undotbs1.258.769030245
259 users.259.769030245
260 current.260.769030435
261 current.261.769030431
262 group_1.262.769030439
263 group_1.263.769030445
264 group_2.264.769030453
265 group_2.265.769030461
266 group_3.266.769030471
267 group_3.267.769030479
268 temp.268.769030503
269 example.269.769030517
270 spfile.270.769030977
我们看到asm实例管理着一组典型的数据库文件。接下来再继续深入剖析。
查询该数据库的控制文件名。
sql> select name "file",
block_size "block size",
block_size*(file_size_blks+1) "file size"
from v$controlfile;
file block size file size
------------------------------------------ ---------- ----------
+data/br/controlfile/current.262.822925011 16384 17973248
+data/br/controlfile/current.261.822925013 16384 17973248
接下来看一下262号文件(current.262.822925011)对应的的文件目录条目。首先,通过查询x$kffxp获得该文件的extent和au分布:
and number_kffxp=262 -- file 262 (control file)
and xnum_kffxp <> 2147483648
virtual extent physical extent allocation unit disk
-------------- --------------- --------------- ----
0 0 776 3
0 1 778 1
0 2 779 2
1 3 781 0
1 4 777 3
1 5 779 1
2 6 780 2
2 7 780 1
2 8 778 3
23 69 795 1
23 70 793 3
23 71 798 0
72 rows selected.
我们看到实例为该文件分配了24个virtual extent,并且该文件是三倍冗余。接下来查询data磁盘组包含的磁盘的编号和路径。
sql> select disk_number, path
from v$asm_disk
disk_number path
----------- ---------
0 /dev/sdb1
1 /dev/sdc1
2 /dev/sdd1
3 /dev/sde1
现在我们通过kfed工具来查看该文件的asm文件目录条目,它会在文件目录的262号block,也就是文件目录中1号extent的6号block(262减去256得出6)。1号extent位于2号磁盘的第48个au,并在1号磁盘的第46个au和0号磁盘的第47个au上分别存在一份冗余。我们只需要看其中一个即可。下面我们来看看2号磁盘的第48个au。
$ kfed read /dev/sdd1 aun=48 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: 262 ; 0x004: blk=262
kfffdb.node.incarn: 822925011 ; 0x000: a=1 numm=0x18866b69
kfffdb.node.frlist.number: 4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn: 0 ; 0x008: a=0 numm=0x0
kfffdb.hibytes: 0 ; 0x00c: 0x00000000
kfffdb.lobytes: 17973248 ; 0x010: 0x01124000
kfffdb.xtntcnt: 72 ; 0x014: 0x00000048
kfffdb.xtnteof: 72 ; 0x018: 0x00000048
kfffdb.blksize: 16384 ; 0x01c: 0x00004000
kfffdb.flags: 19 ; 0x020: o=1 s=1 s=0 d=0 c=1 i=0 r=0 a=0
kfffdb.filetype: 1 ; 0x021: 0x01
kfffde[0].xptr.au: 776 ; 0x4a0: 0x00000308
kfffde[0].xptr.disk: 3 ; 0x4a4: 0x0003
kfffde[0].xptr.flags: 0 ; 0x4a6: l=0 e=0 d=0 s=0
kfffde[0].xptr.chk: 34 ; 0x4a7: 0x22
kfffde[1].xptr.au: 778 ; 0x4a8: 0x0000030a
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: 34 ; 0x4af: 0x22
kfffde[2].xptr.au: 779 ; 0x4b0: 0x0000030b
kfffde[2].xptr.disk: 2 ; 0x4b4: 0x0002
kfffde[2].xptr.flags: 0 ; 0x4b6: l=0 e=0 d=0 s=0
kfffde[2].xptr.chk: 32 ; 0x4b7: 0x20
$
通过以上kfed命令输出中的第一部分kfbh字段,我们确认这是一个asm文件目录的block(kfbh.type=kfbtyp_filedir),而且是描述262号文件的(kfbh.block.blk=262)。
第二部分kfffdb字段则包含:
· file incarnation number (kfffdb.node.incarn=822925011), 文件的incarnation号,属于文件名的一部分
· file size in bytes (kfffdb.lobytes=17973248) 文件的大小
· physical extent count (kfffdb.xtntcnt=72) 文件的物理extent数
· file block size in bytes (kfffdb.blksize=16384) 文件的块大小
· file type (kfffdb.filetype=1), i.e. the database control file 文件的类型,这里为控制文件
第三部分kfffde为物理extent分布,这部分输出与从x$kffxp中查询到的结果一致:
physical extent 0 在 au 776 (kfffde[0].xptr.au=776), 在 disk 3 (kfffde[0].xptr.disk=3) physical extent 1 在 au 778 (kfffde[1].xptr.au=778), 在 disk 1 (kfffde[1].xptr.disk=1) physical extent 2 在 au 779 (kfffde[2].xptr.au=779), 在 disk 2 (kfffde[2].xptr.disk=2)
以此类推
本文中所指的大文件指的是超过60个extent的文件。
先到数据库中找出几个大的文件:
sql> select name, bytes/1024/1024 "size (mb)"
from v$datafile;
name size (mb)
-------------------------------------------- ----------
+data/br/datafile/system.256.769030243 720
+data/br/datafile/sysaux.257.769030245 590
+data/br/datafile/undotbs1.258.769030245 105
+data/br/datafile/users.259.769030245 5
+data/br/datafile/example.269.769030517 345.625
以system表空间的数据文件为例,我们看一下该文件对应的文件目录条目。该文件编号为256,大小为720mb。
sql> select xnum_kffxp "extent", au_kffxp "au", disk_kffxp "disk"
where group_kffxp=1 and number_kffxp=256 and xnum_kffxp <> 2147483648
order by 1,2;
extent au disk
---------- ---------- ----------
0 42 1
0 48 2
1 43 1
1 49 0
2 44 1
2 45 3
720 1111 1
720 1119 2
1442 rows selected.
我们看到asm实例为该文件分配了1442个物理extent。
我们再次用kfed工具来查看该文件的文件目录条目。它位于asm文件目录的256号block,这个块位于48号au,块0。让我们查看0号disk第48个au的0号block。
译者注:1号文件的第一个au保留的是1-255号文件的信息(元信息文件),我们的256号文件,要从1号文件的第二个au开始算起,由于au的块编号是从0号块开始,因此256号文件位于第二个au也就是48号au的0号块。
$ kfed read /dev/sdb1 aun=48 blkn=0 | more
kfbh.hard: 130 ; 0x001: 0x82
kfffdb.node.incarn: 769030243 ; 0x000: a=1 numm=0x16eb3c31
kfffdb.node.frlist.number: 4294967295 ; 0x004: 0xffffffff
kfffdb.lobytes: 754982912 ; 0x010: 0x2d002000
kfffdb.xtntcnt: 1442 ; 0x014: 0x000005a2
kfffdb.xtnteof: 1442 ; 0x018: 0x000005a2
kfffdb.blksize: 8192 ; 0x01c: 0x00002000
kfffdb.flags: 17 ; 0x020: o=1 s=0 s=0 d=0 c=1 i=0 r=0 a=0
kfffdb.filetype: 12 ; 0x021: 0x0c
kfffde[0].xptr.au: 48 ; 0x4a0: 0x00000030
kfffde[0].xptr.disk: 2 ; 0x4a4: 0x0002
kfffde[0].xptr.flags: 0 ; 0x4a6: l=0 e=0 d=0 s=0
kfffde[0].xptr.chk: 24 ; 0x4a7: 0x18
kfffde[1].xptr.au: 42 ; 0x4a8: 0x0000002a
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: 1 ; 0x4af: 0x01
kfffde[2].xptr.au: 49 ; 0x4b0: 0x00000031
kfffde[2].xptr.disk: 0 ; 0x4b4: 0x0000
kfffde[2].xptr.flags: 0 ; 0x4b6: l=0 e=0 d=0 s=0
kfffde[60].xptr.au: 58 ; 0x680: 0x0000003a
kfffde[60].xptr.disk: 1 ; 0x684: 0x0001
kfffde[60].xptr.flags: 0 ; 0x686: l=0 e=0 d=0 s=0
kfffde[60].xptr.chk: 17 ; 0x687: 0x11
kfffde[61].xptr.au: 64 ; 0x688: 0x00000040
kfffde[61].xptr.disk: 0 ; 0x68c: 0x0000
kfffde[61].xptr.flags: 0 ; 0x68e: l=0 e=0 d=0 s=0
kfffde[61].xptr.chk: 106 ; 0x68f: 0x6a
kfffde[62].xptr.au: 63 ; 0x690: 0x0000003f
kfffde[62].xptr.disk: 2 ; 0x694: 0x0002
kfffde[62].xptr.flags: 0 ; 0x696: l=0 e=0 d=0 s=0
kfffde[62].xptr.chk: 23 ; 0x697: 0x17
kfffde[63].xptr.au: 4294967295 ; 0x698: 0xffffffff
kfffde[63].xptr.disk: 65535 ; 0x69c: 0xffff
kfffde[63].xptr.flags: 0 ; 0x69e: l=0 e=0 d=0 s=0
0-59号extent(kfffde[0]-kfffde[59])被称作directly addressed extent,因为它们直接指向数据extent。而编号59以上的extent,被称为indirectly addressed extent,因为它们指向的extent持有的是剩余extent的信息。
接下来对1号磁盘(kfffde[60].xptr.disk=1)的58号au(kfffde[60].xptr.au=58)进行查看。
$ kfed read /dev/sdc1 aun=58 | more
kfbh.type: 12 ; 0x002: kfbtyp_indirect
kffixe[0].xptr.au: 59 ; 0x00c: 0x0000003b
kffixe[0].xptr.disk: 3 ; 0x010: 0x0003
kffixe[0].xptr.flags: 0 ; 0x012: l=0 e=0 d=0 s=0
kffixe[0].xptr.chk: 18 ; 0x013: 0x12
kffixe[1].xptr.au: 64 ; 0x014: 0x00000040
kffixe[1].xptr.disk: 2 ; 0x018: 0x0002
kffixe[1].xptr.flags: 0 ; 0x01a: l=0 e=0 d=0 s=0
kffixe[1].xptr.chk: 104 ; 0x01b: 0x68
kffixe[2].xptr.au: 59 ; 0x01c: 0x0000003b
kffixe[2].xptr.disk: 1 ; 0x020: 0x0001
kffixe[2].xptr.flags:
<b>本文来自云栖社区合作伙伴“dbgeek”</b>