如何利用bbed来修改asm diskgroup中的数据(修复坏块方法类似)?
本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客
很多时候,我们面临一个问题,对于asm diskgroup中的数据文件,如果存在坏块,要么通过备份进行恢复要么进行blockrecover,除了这2种方法之外,对于绝大多数人来讲,我想都是没招儿了。其实不然,你还可以利用bbed来进行修复。这里我没有模拟坏块,仅仅是利用bbed来模拟直接修改asm diskgroup中的表数据,方法类似。
++++创建测试表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
SQL> create table t0727(a number); Table created. SQL> insert into t0727 values(1); 1 row created. SQL> insert into t0727 values(10); 1 row created. SQL> insert into t0727 values(100); 1 row created. SQL> commit; Commit complete. SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) blk# from t0727; FILE# BLK# ---------- ---------- 5 28 5 28 5 28 |
这里我需要将第3条数据100修改为99.
通过将该block copy到文件系统,然后bbed修改数据,然后再copy到asm diskgroup。
++++copy block to filesystem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SQL> @cp_block_to_fs.sql Enter value for asm_file_name: +DATA1/test/datafile/roger.260.831967031 old 14: v_AsmFilename := '&ASM_File_Name'; --asm file name new 14: v_AsmFilename := '+DATA1/test/datafile/roger.260.831967031'; --asm file name Enter value for block_to_extract: 28 old 15: v_offstart := '&block_to_extract'; --block id new 15: v_offstart := '28'; --block id Enter value for number_of_blocks_to_extract: 1 old 16: v_numblks := '&number_of_blocks_to_extract'; --number of blocks to patch new 16: v_numblks := '1'; --number of blocks to patch Enter value for filesystem_file_name: /home/oracle/file_528.dbf old 17: v_FsFilename := '&FileSystem_File_Name'; new 17: v_FsFilename := '/home/oracle/file_528.dbf'; PL/SQL procedure successfully completed. |
+++++使用bbed 修改数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
BBED> set file 5 block 1 FILE# 5 BLOCK# 1 BBED> map File: /home/oracle/file_528.dbf (5) Block: 1 Dba:0x01400001 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 72 bytes @20 struct kdbh, 14 bytes @100 struct kdbt[1], 4 bytes @114 sb2 kdbr[3] @118 ub1 freespace[8046] @124 ub1 rowdata[18] @8170 ub4 tailchk @8188 BBED> BBED> p kdbr sb2 kdbr[0] @118 8082 sb2 kdbr[1] @120 8076 sb2 kdbr[2] @122 8070 BBED> p *kdbr[2] rowdata[0] ---------- ub1 rowdata[0] @8170 0x2c BBED> x /rccxxxxxxx rowdata[0] @8170 ---------- flag@8170: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@8171: 0x01 cols@8172: 1 col 0[2] @8173: BBED> d /v offset 8173 count 4 File: /home/oracle/file_528.dbf (5) Block: 1 Offsets: 8173 to 8176 Dba:0x01400001 ------------------------------------------------------- 02c2022c l ., <16 bytes per line> BBED> modify /x c164 offset 8174 File: /home/oracle/file_528.dbf (5) Block: 1 Offsets: 8174 to 8177 Dba:0x01400001 ------------------------------------------------------------------------ c1642c01 <32 bytes per line> BBED> sum apply Check value for File 5, Block 1: current = 0x32a7, required = 0x32a7 |
修改完成之后,我们需要将block从文件系统copy回asm diskgroup中,如下:
++++copy block to asm diskgroup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
SQL> set serveroutput on SQL> @cp_block_to_asm.sql Enter value for file_with_patched_block: /home/oracle/file_528.dbf old 15: v_FsFileName := '&file_with_patched_block'; new 15: v_FsFileName := '/home/oracle/file_528.dbf'; Enter value for file_to_patch_in_asm: +DATA1/test/datafile/roger.260.831967031 old 16: v_AsmFileName := '&file_to_patch_in_ASM'; new 16: v_AsmFileName := '+DATA1/test/datafile/roger.260.831967031'; Enter value for block_to_patch: 28 old 17: v_offstart := '&block_to_patch'; new 17: v_offstart := '28'; File: +DATA1/test/datafile/roger.260.831967031 Type: 12 Data File Copy Size (in logical blocks): 25600 Logical Block Size: 8192 Physical Block Size: 512 File: +DATA1/test/datafile/roger.260.831967031 Type: 12 Data File Copy Size: 25600 Logical Block Size: 8192 PL/SQL procedure successfully completed. |
验证数据是否修改成功,如下所示:
1 2 3 4 5 6 7 8 9 10 11 |
SQL> alter system flush buffer_cache; System altered. SQL> select * from t0727; A ---------- 1 10 99 |
这里是利用了metalink的copy 脚本,其实我们也可以手工进行操作,dbsnake之前写过一篇文章,不过该文章
有点不够完整,这里我进行补充一下,搞个完整版本。
这里我的演示,主要通过将t0727表中的第3条数据通过bbed修改为98.如下是整个实验的过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SQL> select name from v$datafile where file#=5; NAME -------------------------------------------------------------------------------- +DATA1/test/datafile/roger.260.831967031 SQL> conn roger/roger Connected. SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) blk# 2 from t0727; FILE# BLK# ---------- ---------- 5 28 5 28 5 28 |
而我们根据block进行计算,发现表表的数据应该在第一个au中,如下:
1 2 3 4 5 6 7 |
SQL> select 28*8192 from dual; 28*8192 ---------- 229376 很明显这是小于1m的(10g asm 默认au是1m)。 |
asm默认block是4096,一个AU容纳256个block,如果换成数据库的8192,那么则是128个block。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
SQL> select disk_kffxp, AU_kffxp, xnum_kffxp 2 from x$kffxp 3 where group_kffxp = 1 4 and number_kffxp = 260 5 order by 3; DISK_KFFXP AU_KFFXP XNUM_KFFXP ---------- ---------- ---------- 1 275 0 0 279 1 1 272 2 0 250 3 1 252 4 0 276 5 1 253 6 0 273 7 1 269 8 0 253 9 .......... 1 506 198 0 483 199 1 482 200 0 406 2147483648 202 rows selected. |
从上面的信息我们可以看出,该数据文件的第一个AU为275,而t0727表在第1个AU中,
根据这样的计算,那么该表t0727的实际位置为;
1 2 3 4 5 6 7 |
SQL> select 275*128+28 from dual; 275*128+28 ---------- 35228 SQL> |
下面我们开始手工dd ASM disk中的该block到文件系统然后进行bbed修改,最后再dd回asm中。
注意,直接dd的block是没有os block 的,如果我们需要用bbed来进行修改,那么就需要为dd出来的block
构造一个os block块。 对于os block header的结构,很早之前我写过一篇文档。
这里我直接用之前asm copy脚本产生的文件来进行构造,构造的方法很简单,将os block header 进行dd,然后
dd拼接到需要修改的block上即可,如下是步骤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@10gasm oracle]# dd if=/home/oracle/file_528.dbf of=/home/oracle/os_header bs=8192 count=1 1+0 records in 1+0 records out 8192 bytes (8.2 kB) copied, 8.3758e-05 seconds, 97.8 MB/s [root@10gasm oracle]# dd if=/home/oracle/dd_file528.dbf of=/home/oracle/os_header bs=8192 seek=1 count=1 conv=notrunc 1+0 records in 1+0 records out 8192 bytes (8.2 kB) copied, 3.9558e-05 seconds, 207 MB/s [root@10gasm oracle]# ls -ltr dd_file528.dbf -rw-r--r-- 1 oracle oinstall 8192 Jul 27 08:35 dd_file528.dbf [root@10gasm oracle]# rm dd_file528.dbf rm: remove regular file `dd_file528.dbf'? y [root@10gasm oracle]# mv os_header dd_file528.dbf |
如果不进行os block header的构造,那么bbed这里会出现问题,你看到的情况可能是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
BBED> map File: /home/oracle/dd_file528.dbf (6) Block: 1 Dba:0x01800001 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 72 bytes @20 struct kdbh, 14 bytes @100 struct kdbt[1], 4 bytes @114 sb2 kdbr[3] @118 ub1 freespace[8046] @124 ub1 rowdata[4294959634] @8170 ub4 tailchk @508 BBED> set file 6 block 1 FILE# 6 BBED-00309: out of range block number (1) |
很明显,上面的信息是有问题的,下面我们通过bbed来进行修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
BBED> map File: /home/oracle/dd_file528.dbf (6) Block: 1 Dba:0x01800001 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 72 bytes @20 struct kdbh, 14 bytes @100 struct kdbt[1], 4 bytes @114 sb2 kdbr[3] @118 ub1 freespace[8046] @124 ub1 rowdata[18] @8170 ub4 tailchk @8188 BBED> p *kdbr[2] rowdata[0] ---------- ub1 rowdata[0] @8170 0x2c BBED> x /rccccccc rowdata[0] @8170 ---------- flag@8170: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@8171: 0x01 cols@8172: 1 col 0[2] @8173: 羋 BBED> d /v offset 8173 count 4 File: /home/oracle/dd_file528.dbf (6) Block: 1 Offsets: 8173 to 8176 Dba:0x01800001 ------------------------------------------------------- 02c1642c l .羋, <16 bytes per line> BBED> modify /x c163 offset 8174 Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y File: /home/oracle/dd_file528.dbf (6) Block: 1 Offsets: 8174 to 8177 Dba:0x01800001 ------------------------------------------------------------------------ c1632c01 <32 bytes per line> BBED> sum apply Check value for File 6, Block 1: current = 0x35a7, required = 0x35a7 |
我们通过bbed修改完成之后,需要再通过dd命令将block 还原到asm disk上,直接dd之前也需要先截取一下,否则
直接dd是会产生坏块的,如下:
1 2 3 4 5 6 7 8 9 |
[oracle@10gasm ~]$ dd if=/home/oracle/dd_file528.dbf of=/home/oracle/dd_528 skip=1 bs=8192 count=1 1+0 records in 1+0 records out 8192 bytes (8.2 kB) copied, 0.0168119 seconds, 487 kB/s [oracle@10gasm ~]$ dd if=/home/oracle/dd_528 of=/dev/sdc bs=8192 seek=35228 count=1 conv=notrunc 1+0 records in 1+0 records out 8192 bytes (8.2 kB) copied, 4.5487e-05 seconds, 180 MB/s [oracle@10gasm ~]$ |
最后来验证一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
SQL> SQL> alter system flush buffer_cache; System altered. SQL> select * from t0727; A ---------- 1 10 98 SQL> |
可以看到,我们已经成功将该表的第3条数据,通过bbed修改为98了。
说明:使用类似的方法来修复asm 坏块,思路完全一致,这里不再累述,本文仅供参考!
Leave a Reply
You must be logged in to post a comment.