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


7 Comments on “ASM里如何修改指定的Block”

  1. JACK says:

    注意这里一定要在这个block之前构造一个OS block header,否则BBED会乱套的。
    —-这里所说的构造一个OS BLOCK HEADER没有明白
    第一,怎么构造。第二,构造的原因。第三OS BLOCK HEAD和DB 的BLOCK HEAD 有什么关联,关联点在什么地方,关联的用途是什么?第三。BBED只是一个应用程序,它怎么会乱套的。
    —-希望能够解答。谢谢崔大师

  2. Sidney says:

    崔华, 我今天做了一下测试, 如果没有dd一个os header block放在前面的话, 会遇到下面的错误, 这个错误是不是你所说的Bug?

    BBED> set offset 1000
    BBED-00206: out of range offset (1000)

    • Cui Hua says:

      判断的原则很简单:一旦你在使用BBED的过程中见到明显违背常识的东西后,就有理由怀疑是BBED的bug了。事实上,BBED的bug有很多。

  3. 李健 says:

    你好:能否指导一下,这个OFFSET怎么算,我测试的一张表,
    select a.*,
    dbms_rowid.rowid_relative_fno(rowid) || ‘_’ ||
    dbms_rowid.rowid_block_number(rowid) location
    from pioro.secret_table a;
    ID NAME CARDNUM LOCATION
    —— ——————- ————– ——————
    1 Marcin Przepiorowski 4444-1111-2222-3333 4_49182
    2 Jim Smith 4444-2222-3333-5555 4_49182
    SQL> select name from v$datafile where file#=4;

    NAME
    —————————————-
    +DATA/orcl/datafile/users.259.835961027
    这个应该不在第一AU里
    select 49176*8/1024 from dual ;
    384.1875

    SELECT disk_kffxp, au_kffxp, xnum_kffxp
    FROM x$kffxp
    WHERE GROUP_KFFXP = 1
    AND NUMBER_KFFXP = 259 and xnum_kffxp between 384 and 385;
    0 7811 384
    0 7812 385

    这个file 4,block 49182的物理offset,应该怎么算,谢谢!!

  4. 李健 says:

    不好意思,忘记介绍了,我的数据库是11GR2的版本。


Leave a Reply

Your email address will not be published. Required fields are marked *