ASM里如何修改指定的Block
Posted: December 12, 2011 | Author: Cui Hua | Filed under: Oracle | Tags: modify ASM block | 5 Comments »当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所对应的EMPNO由7369改为7370,我们现在知道这个block的DBA是file 4,block 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
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 number是259。
SQL> select 32*8192 from dual;
32*8192
———-
262144
262144小于
然后我们转到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所在的第一个AU被normal redundancy了,其物理地址分别在disk 0和disk 1的第834个AU,因为这里是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。

注意这里一定要在这个block之前构造一个OS block header,否则BBED会乱套的。
—-这里所说的构造一个OS BLOCK HEADER没有明白
第一,怎么构造。第二,构造的原因。第三OS BLOCK HEAD和DB 的BLOCK HEAD 有什么关联,关联点在什么地方,关联的用途是什么?第三。BBED只是一个应用程序,它怎么会乱套的。
—-希望能够解答。谢谢崔大师
1、找到os header block的位置,直接dd出来就可以了;
2、这是BBED的bug,你试一下就知道了
多谢!
崔华, 我今天做了一下测试, 如果没有dd一个os header block放在前面的话, 会遇到下面的错误, 这个错误是不是你所说的Bug?
BBED> set offset 1000
BBED-00206: out of range offset (1000)
判断的原则很简单:一旦你在使用BBED的过程中见到明显违背常识的东西后,就有理由怀疑是BBED的bug了。事实上,BBED的bug有很多。