Where is the backup of ASM disk header block?

在Oracle 10.2.0.5之前,ASM磁盘的头块并没有自己的备份,因此一旦头块损坏,如果没有以前kfed read备份出来的信息,也就没有办法使用kfed merge来作头块恢复,特别是如果一个磁盘组中所有的磁盘头块都出现问题(比如被人为地创建了PV),恢复ASM磁盘头块的操作就会非常麻烦。

但是从Oracle 10.2.0.5之后,ASM磁盘的头块会自动备份在另外一个块中,这实际上是Oracle 11g出现的功能,不过经过测试,在Oracle 10.2.0.5版本中,这个备份也是存在的。

正是因为存在这个备份,所以Oracle 10.2.0.5之后的kfed程序才有了新的repair命令,该命令将备份块直接覆盖到磁盘头块,完成修复工作。

在Oracle 10.2.0.4中,如果尝试执行kfed repair,则会报错说命令行参数不正确,此报错说明并不存在repair命令:

$ kfed repair 
KFED-00101: LRM error [102] while parsing command line arguments

但是在Oracle 10.2.0.5中,执行kfed repair,则会说无法打开文件空,而这正说明repair命令是存在的,报错是因为还需要明确指定要修复哪块磁盘:

$ kfed repair
KFED-00303: unable to open file ''

那么这个备份块具体存在哪里呢?在Solaris下的测试,我们使用truss来进行跟踪。

$ truss -o tracedisk2.out kfed repair /asmdisks/vdisk2

在trace文件中,找到下面这段,可以明确地看到kfed程序从第510个块中读出4096字节,然后再写回到第0个块中。

stat("/asmdisks/vdisk2", 0xFFFFFD7FFFDFDB20)    = 0
open("/asmdisks/vdisk2", O_RDWR)                = 7
lseek(7, 0x001FE000, SEEK_SET)                  = 2088960	<-- 1FE is 510
read(7, "01820101FE\0\0\0\0\0\080".., 4096)     = 4096		<-- read 4096 bytes
lseek(7, 0, SEEK_SET)                           = 0		
read(7, "01820101\0\0\0\0\0\0\080".., 4096)     = 4096		
lseek(7, 0, SEEK_SET)                           = 0		<-- 0 is 0
write(7, "01820101\0\0\0\0\0\0\080".., 4096)    = 4096		<-- write 4096 bytes
close(7)

同样如果是在Linux下用裸设备作为ASM磁盘,并且用strace进行repair命令的跟踪,也可以得到类似结果。

open("/dev/raw/raw3", O_RDWR)           = 5
lseek(5, 2088960, SEEK_SET)             = 2088960	<-- 2088960/4096=510
read(5, "\1\202\1\1\0\0\0\0\0\0\0\200evx\257\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
lseek(5, 0, SEEK_SET)                   = 0
read(5, "\1\202\1\1\0\0\0\0\0\0\0\200evx\257\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
lseek(5, 0, SEEK_SET)                   = 0
write(5, "\1\202\1\1\0\0\0\0\0\0\0\200evx\257\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
close(5)                                = 0

那么通过kfed命令再来验证一下这两个块是否都标志为头块。验证结果表示块类型都为DISKHEAD。

$ kfed read /asmdisks/vdisk2 blkn=0 | grep KFBTYP
kfbh.type:                            1 ; 0x002: KFBTYP_DISKHEAD
$ kfed read /asmdisks/vdisk2 blkn=510 | grep KFBTYP
kfbh.type:                            1 ; 0x002: KFBTYP_DISKHEAD <-- this is the backup!!

那么下一个疑问是,在11gR2以后,ASM磁盘组的AU Size可以指定不同的大小,是不是不同的AU Size下的磁盘头块备份都是在第510个块呢?还是用truss来跟踪一下,这里的vdisk3属于一个AU Size=8M的磁盘组,此时repair命令需要明确指定aus,否则会报KFED-00320错误。

truss -o tracedisk3.out kfed repair /asmdisks/vdisk3 aus=8388608

在trace文件中,可以发现已经不再是去读第510个块,而是改为读第4094个块。

stat("vdisk3", 0xFFFFFD7FFFDFDB10)              = 0
open("vdisk3", O_RDWR)                          = 7
lseek(7, 0x00FFE000, SEEK_SET)                  = 16769024	<--FFE is 4094
read(7, "01820101FE07\0\0\0\0\080".., 4096)     = 4096
lseek(7, 0, SEEK_SET)                           = 0
read(7, "01820101\0\0\0\0\0\0\080".., 4096)     = 4096
lseek(7, 0, SEEK_SET)                           = 0
write(7, "01820101\0\0\0\0\0\0\080".., 4096)    = 4096
close(7)

用kfed验证第4094个块,确实标志为DISKHEAD。

$ kfed read /asmdisks/vdisk3 blkn=4094 | grep KFBTYP
kfbh.type:                            1 ; 0x002: KFBTYP_DISKHEAD

那么也就是AU 1M的磁盘组头块备份在第510个块上,而AU 8M的磁盘组头块备份在第4094个块上,备份块的存储位置有规律吗?有的,始终保存在第2个AU的倒数第2个块上。下面来验证这个观点。

对于默认的磁盘组,AU Size=1M,每个AU中可以存储256个块,块号为0-255。第1个AU存储256个块,第2个AU最后1个块号为255,倒数第2个块号是254,也就是整体的第510个块(从第1个AU的第1个块往后算起)。

$ kfed read /asmdisks/vdisk2 blkn=0 | grep ausize
kfdhdb.ausize:                  1048576 ; 0x0bc: 0x00100000
$ kfed read /asmdisks/vdisk2 blkn=0 | grep blksize
kfdhdb.blksize:                    4096 ; 0x0ba: 0x1000
$ let r=1048576/4096;echo $r
256
$ let r=256+255-1;echo $r
510

对于AU Size=8M的磁盘组,每个AU可以存储2048个块,块号为0-2047。第1个AU存储2048个块,第2个AU最后1个块号为2047,倒数第2个块号是2046,也就是整体的第4094个块(从第1个AU的第1个块往后算起)。

$ kfed read /asmdisks/vdisk3 blkn=0 | grep ausize
kfdhdb.ausize:                  8388608 ; 0x0bc: 0x00800000
$ kfed read /asmdisks/vdisk3 blkn=0 | grep blksize
kfdhdb.blksize:                    4096 ; 0x0ba: 0x1000
$ let r=8388608/4096;echo $r
2048
$ let r=2048+2047-1;echo $r
4094

对于其它AU Size磁盘组的验证,看到文章的朋友有兴趣可以自己做一下。

结论:
从Oracle 10.2.0.5开始,ASM磁盘已经开始自动将头块进行备份,备份块的位置在第2个AU的倒数第2个块上(对于默认1M的AU来说,是第510个块),如果头块损坏,可以用kfed repair命令来修复。因此对于选用ASM存储作为生产环境的用户来说,尽快升级到10.2.0.5是明智的选择。

How to use asmca to create ASM instance silently in Oracle 11gR2

对于只能登录字符界面的很多服务器而言,能够使用silent模式创建一些组件是至关重要的。本文介绍如何在字符界面下使用asmca来创建ASM实例。

测试环境:Oracle 11.2.0.3 + Oracle Restart 【关于Oracle Restat,可以参看我之前的文章-How to Use Oracle Restart in Oracle 11gR2

在没有创建ASM实例之前,Clusterware中的资源状况如下:

grid@solaris:~$ ct
--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER                   STATE_DETAILS       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER_SOLARIS.lsnr
               ONLINE  ONLINE       solaris                                      
ora.ons
               OFFLINE OFFLINE      solaris                                      
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        OFFLINE OFFLINE                                                   
ora.diskmon
      1        OFFLINE OFFLINE                                                   
ora.evmd
      1        ONLINE  ONLINE       solaris                                      
ora.orcl.db
      1        ONLINE  ONLINE       solaris                  Open                

通过如下命令用gird用户创建ASM实例。

asmca -silent -configureASM -sysAsmPassword oracle -asmsnmpPassword oracle -diskString '/asmdisks/vdisk*' -diskGroupName DATADG -disk '/asmdisks/vdisk1' -redundancy EXTERNAL

-silent:表示静默模式,这在字符界面中至关重要。
-configureASM:表示本命令是用于配置ASM实例,如果ASM实例不存在,则会新建。
-sysAsmPassword:sysasm权限用户的密码。
-asmsnmpPassword:asmsnmp权限用户的密码。如果用过asmca图形界面的应该记得这两个密码在图形界面中都是需要输入的。
-diskString:ASM磁盘组的磁盘发现路径。
-diskGroupName:需要新建的磁盘组名称。
-disk:ASM磁盘名称。
-redundancy:磁盘冗余方式,本例中使用了外部冗余。

会有大量的屏幕输出,但是最后显示如下行表示命令成功完成。

ASM created and started successfully.

Disk Group DATADG created successfully.

再次检查Clusterware的资源状况,可以看到已经增加了ASM资源,并且已经正常启动。

grid@solaris:~$ ct
--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER                   STATE_DETAILS       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER_SOLARIS.lsnr
               ONLINE  ONLINE       solaris                                      
ora.asm
               ONLINE  ONLINE       solaris                  Started             
ora.ons
               OFFLINE OFFLINE      solaris                                      
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        ONLINE  ONLINE       solaris                                      
ora.diskmon
      1        OFFLINE OFFLINE                                                   
ora.evmd
      1        ONLINE  ONLINE       solaris                                      
ora.orcl.db
      1        ONLINE  ONLINE       solaris                  Open                

查看ASM磁盘组状况。

ASMCMD> lsdg
State    Type    Rebal  Sector  Block       AU  Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  EXTERN  N         512   4096  1048576       976      917                0             917              0             N  DATADG/

接下来增加一个磁盘到该磁盘组中,同样通过asmca来完成,当然这个操作也可以用SQL*Plus中的alter diskgroup命令来完成。

asmca -silent -addDisk -diskGroupName DATADG -disk '/asmdisks/vdisk2' -sysAsmPassword oracle

同样会有大量输出,最后显示如下行表示操作完成。

Disks added successfully to disk group DATADG

再次检查ASM磁盘组状况。可以看到磁盘组容量已经扩充。

ASMCMD> lsdg
State    Type    Rebal  Sector  Block       AU  Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  EXTERN  N         512   4096  1048576      1952     1891                0            1891              0             N  DATADG/  

如果想获得asmca的帮助,可以通过以下命令。

asmca -help

How to use iperf to test network bandwith

测试Linux机器之间的网络互联带宽,有一个很简单的工具,iperf

下载的是源码,编译过程如下:

./configure
make
make install

安装完毕以后,iperf的路径:

# which iperf
/usr/local/bin/iperf

然后在需要测试的两台Linux机器上,一台启动服务器模式。

# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------

另外一台启动客户端模式,其中IP地址为启动服务器模式的机器的IP,稍等片刻,即可出现测试结果。

# iperf -c 192.168.0.19
------------------------------------------------------------
Client connecting to 192.168.0.19, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.0.18 port 16265 connected with 192.168.0.19 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   114 MBytes  95.5 Mbits/sec

同时,启动服务器模式的机器上也会显示:

[  4] local 192.168.0.19 port 5001 connected with 192.168.0.18 port 16265
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.1 sec   114 MBytes  94.9 Mbits/sec

可知,这两台机器之间的互联带宽仅仅达到百兆网的速度。