一个客户的RAC环境出现了故障,一个节点操作系统崩溃,重装系统后,CLUSTER添加成功,但是ASM实例添加报错。
这一篇描述问题的诊断。
当时通过电话简单了解了一下情况:Oracle 10204 RAC for Linux X86-64的环境,前一段时间操作系统出现了故障,导致一个节点重装。重装过程到了添加ASM实例的时候出现了错误。
一般来说,重装过程最复杂的是CLUSTER的清除和添加,如果CLUSTER已经添加成功,那么剩下的就是数据库级的操作,相对来说会简单得多。根据上面的信息初步判断,问题可能发生在几点,新节点的ORACLE_HOME的版本和旧节点不一致,或者10204补丁没有在CLUSTER上安装,或者是在新节点上没有给oracle用户授权,还有可能就是共享存储在新节点上挂载存在问题。
到了现场后才发现,问题和我的判断大相径庭,数据库的版本,权限等都不存在问题,事实上,新节点上的ASM实例已经启动,且两个磁盘组中的一个已经MOUNT,但另外一个磁盘组无法MOUNT:
SQL> alter diskgroup datag1
mount;
alter diskgroup datag1 mount
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15063: ASM discovered an insufficient number of disks for diskgroup
"DATAG1"
ORA-15032只是一个描述性错误,而关键的ORA-15063错误比较少见。
由于另外一个节点从RAC环境出现故障后一直没有停机,因此可以从这个节点的ASM实例上检查磁盘组和磁盘的状态:
SQL> select group_number, name, state, total_mb, free_mb from v$asm_diskgroup;
GROUP_NUMBER NAME
STATE
TOTAL_MB FREE_MB
------------ ------------------------------------ ---------- ----------
1 DATAG1 MOUNTED 512000 217396
2 DATAG2 MOUNTED 1024000 347457
SQL> select group_number, disk_number, mount_status, header_status, name, path from v$asm_disk where group_number = 1;
GROUP_NUMBER DISK_NUMBER MOUNT_STATUS HEADER_STATUS NAME
PATH
------------ ----------- ------------ -------------- ----------- -------------
1 0 CACHED PROVISIONED DATAG1_0000 /dev/raw/raw4
1 1 CACHED MEMBER DATAG1_0001 /dev/raw/raw5
SQL> select instance_number, instance_name from v$instance;
INSTANCE_NUMBER INSTANCE_NAME
--------------- --------------------------------
2 +ASM2
可以看到,磁盘组DATAG1中的磁盘DATAG1_0000的文件头状态不正确。从新添加的实例1上检查ASM磁盘信息:
SQL> select group_number, name, state, total_mb, free_mb from v$asm_diskgroup;
GROUP_NUMBER NAME
STATE
TOTAL_MB FREE_MB
------------ ------------------------------------ ---------- ----------
1 DATAG1 DISMOUNTED 0 0
2 DATAG2 MOUNTED 1024000 347457
SQL> select group_number, disk_number, mount_status, header_status, name, path from v$asm_disk;
GROUP_NUMBER DISK_NUMBER MOUNT_STATUS HEADER_STATUS NAME
PATH
------------ ----------- ------------ -------------- ----------- --------------
0 0 CLOSED FOREIGN /dev/raw/raw1
0 1 CLOSED FOREIGN /dev/raw/raw2
0 2 CLOSED FOREIGN /dev/raw/raw8
0 3 CLOSED FOREIGN /dev/raw/raw10
0 4 CLOSED FOREIGN /dev/raw/raw9
0 8 CLOSED PROVISIONED /dev/raw/raw4
0 5 CLOSED MEMBER /dev/raw/raw5
2 1 CACHED
MEMBER DATAG2_0001
/dev/raw/raw7
2 0 CACHED MEMBER DATAG2_0000 /dev/raw/raw6
SQL> select instance_number, instance_name from v$instance;
INSTANCE_NUMBER INSTANCE_NAME
--------------- --------------------------------
1 +ASM1
由于节点1上的ASM磁盘组1无法MOUNT,因此可以看到/dev/raw/raw4和/dev/raw/raw5两个磁盘对应的GROUP_NUMBER是0,且MOUNT_STATUS是CLOSED,而raw4对应的HEADER_STATUS也是PROVISIONED,显然就是这个错误的状态值导致当前节点无法MOUNT磁盘组。
由于另外一个实例一直没有关闭过,因此虽然磁盘头的状态不正常,但是并不影响这个磁盘组的正常使用,而如果这时对ASM实例进行重启,则这个磁盘组必然无法再次MOUNT。
根据Oracle的文档的描述,PROVISIONED和CANDIDATE状态有所区别,二者虽然表示的都是这个磁盘为候选磁盘,不属于任何一个磁盘组,不过CANDIDATE是正常的候选状态,而PROVISIONED则说明磁盘经过特殊的处理,比如操作系统工具对磁盘进行过特殊的操作。
既然这个磁盘的状态是PROVISIONED,那么能否通过再次添加这个磁盘到磁盘组,使得磁盘头的状态变成正常。于是尝试在问题节点再次添加这个磁盘,但是由于磁盘组处于NOMOUNT状态,导致添加操作失败,而尝试在目前正常工作的节点添加磁盘,结果同样报错:
SQL> alter diskgroup datag1 add disk '/dev/raw/raw4';
alter diskgroup datag1 add disk '/dev/raw/raw4'
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15029: disk '/dev/raw/raw4' is already mounted by this instance
看来常规手段已经无法解决这个问题,那么现在只剩两个办法,一是重建ASM磁盘,二是直接修改ASM磁盘头信息。
重建意味着较长的停机时间,既是客户当前环境中配置了DATA GUARD,重建ASM磁盘组也不是一个轻松的事情。当前的PRIMARY数据库和STANDBY数据库都是两节点的RAC环境,而在数据库中还配置STREAM的CAPTURE,这本身使得数据库架构异常复杂,进行SWITCHOVER的难度相对也比较大。而且对于当前运行的节点而言,一旦关闭,很有可能导致ASM磁盘无法MOUNT,这就会导致原本计划中的SWITCHOVER变成FAILOVER,甚至有可能损失ONLINE REDO LOGFILE的风险,因此无论从哪个角度看,重建都不是一个最佳的解决方案,显然如果能直接将ASM磁盘的头信息改写正确,这无疑是最直接代价最小的解决方案。