ASM里如何修改指定的Block

ASM下的库坏了起不来的时候,我们怎么办?

这时候如果你没有有效备份的话你可能会需要修改ASM下的指定block这时候怎么找到这个指定block的物理存储地址成了问题的关键!

 

在你真正面临上述问题的时候,一般情况下不太可能会让你有机会用RMAN或者DBMS_FILE_TRANSFER把有问题的文件拷出来,因为一来file system的容量有限,可能放不下;二来因为需要修改一个block就把整个文件都拷出来,改了后再拷回去——这个可能恢复的时间根本就不允许你这么做。

 

我们现在来看一个ASM下修改指定block的实例,善用我这里的方法在某些特殊的情况下是可以救命的:

SQL> select empno,ename,dbms_rowid.rowid_relative_fno(rowid)||’_’||dbms_rowid.rowid_block_number(rowid) location from scott.emp;

 

     EMPNO ENAME      LOCATION

———- ———- ———————————————————————————

      7369 SMITH      4_32

      7499 ALLEN      4_32

      7521 WARD       4_32

      ……省略显示部分内容

      7934 MILLER     4_32

 

14 rows selected.

 

假定这里我们要把SMITH所对应的EMPNO7369改为7370,我们现在知道这个blockDBAfile 4block 32

 

我们现在把上述实例shutdown后再mount——这就模拟了ASM下库起不来的情况:

[oracle@rac1 db_1]$ srvctl stop instance -d cuihua -i cuihua1

[oracle@rac1 db_1]$ export ORACLE_SID=cuihua1

[oracle@rac1 db_1]$ sqlplus ‘/ as sysdba’;

 

SQL*Plus: Release 10.2.0.1.0 – Production on Fri May 7 09:08:34 2010

 

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

 

Connected to an idle instance.

 

SQL> startup mount

ORACLE instance started.

 

Total System Global Area  209715200 bytes

Fixed Size                  1218556 bytes

Variable Size              88082436 bytes

Database Buffers          117440512 bytes

Redo Buffers                2973696 bytes

Database mounted.

 

SQL> select name from v$datafile where file#=4;

 

NAME

——————————————————————————–

+DGDATA/cuihua/datafile/users.259.651595941

这里我们知道了file 4所对应的ASM internal file number259

 

SQL> select 32*8192 from dual;

 

   32*8192

———-

262144

262144小于1M,所以file 4,block 32一定在259所对应的第一个AU上。

 

然后我们转到ASM instance

SQL> select NUMBER_KFFXP, XNUM_KFFXP, GROUP_KFFXP, DISK_KFFXP,AU_KFFXP from X$KFFXP where NUMBER_KFFXP = 259;

 

NUMBER_KFFXP XNUM_KFFXP GROUP_KFFXP DISK_KFFXP   AU_KFFXP

———— ———- ———– ———- ———-

         259          0           1          1        834

         259          0           1          0        834

         259          1           1          0        835

         259          1           1          1        835

          ……省略显示部分内容

         259         55           2          0        277

 

68 rows selected.

 

SQL> select NAME, PATH from v$asm_disk where GROUP_NUMBER=1 and DISK_NUMBER=0;

 

NAME                                                         PATH

———————————————————— ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–

DGDATA_0000                                                  /dev/raw/raw3

 

SQL> select NAME, PATH from v$asm_disk where GROUP_NUMBER=1 and DISK_NUMBER=1;   

 

NAME                                                         PATH

———————————————————— ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–

DGDATA_0001                                                  /dev/raw/raw4

这里我们可以看到259所在的第一个AUnormal redundancy了,其物理地址分别在disk 0disk 1的第834AU,因为这里是normal redundancy,所以我们改完后覆盖的时候要覆盖这两个地方。

 

现在我们来算一下file 4,block 32的物理offset

SQL> select (834*1048576+262144)/8192 from dual;

 

(834*1048576+262144)/8192

————————-

                   106784

 

至此,我们已经完全知道了file 4,block 32的实际物理存储地址。

 

现在我们就可以用dd把这个block拷出来了:

[oracle@rac1 ASMDump]$ dd if=/dev/raw/raw3 of=emp_4_32.dmp bs=8192 skip=106784 count=1

读入了 1+0 个块

输出了 1+0 个块

 

拷出来后就可以用BBED修改这个块了,注意这里一定要在这个block之前构造一个OS block header,否则BBED会乱套的

 

BBED改完了后我们再用dd把修改后的block拷回去:

[oracle@rac1 ASMDump]$ dd if=emp_4_32.dmp of=/dev/raw/raw3 bs=8192 seek=106784 count=1 conv=notrunc

读入了 1+0 个块

输出了 1+0 个块

 

[oracle@rac1 ASMDump]$ dd if=emp_4_32.dmp of=/dev/raw/raw4 bs=8192 seek=106784 count=1 conv=notrunc

读入了 1+0 个块

输出了 1+0 个块

 

拷完后我们起一下库,现在我们来看一下修改后的效果:

SQL> select empno,ename from scott.emp;

 

     EMPNO ENAME

———- ———-

      7370 SMITH

      7499 ALLEN

      7521 WARD

      ……省略显示部分内容

      7934 MILLER

 

14 rows selected.

 

可以看到我们已经成功的把7369改成了7370