且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[20171115]恢复数据文件块头3补充.txt

更新时间:2022-08-15 08:28:49

[20171115]恢复数据文件块头3补充.txt

--// 昨天做了恢复数据文件块头,通过备份文件直接取出文件块头,覆盖原来的数据块,然后修复.
--//补充几点:
--1.文件头损坏,无法使用rman的块恢复功能.
--2.文件头损坏,dbv检查发现都是坏块.我感觉主要文件块头损坏,dbv无法定位其它剩下的块.

1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

2.建立测试环境:

CREATE TABLESPACE TEA DATAFILE
  '/mnt/ramdisk/book/tea01.dbf' SIZE 40M AUTOEXTEND ON NEXT 16M MAXSIZE UNLIMITED
LOGGING
ONLINE
EXTENT MANAGEMENT LOCAL AUTOALLOCATE
BLOCKSIZE 8K
SEGMENT SPACE MANAGEMENT AUTO
FLASHBACK ON;

create table t1 tablespace tea as select rownum id ,lpad('A',32,'A') name from dual connect by level<=1e5;

--//建立rman备份:
backup database filesperset=1 format '/home/oracle/backup/20171114_%U';
--//注:这是我个人主张的备份方式设置filesperset=1,可惜我们团队一直不建议使用.这样备份文件显得太多了.实际上这样做与我后面的恢复有关.

create table t2 tablespace tea as select rownum id ,lpad('B',32,'B') name from dual connect by level<=1e5;
--//建立大小5M的表。注:说明一点,我是先做数据库备份,再建立t2表.
--//破坏数据文件头,注:数据文件头在数据文件的第2块.第1块OS头.

update t2 set name=lpad('C',32,'C') where id <=5;
alter system checkpoint;
alter system checkpoint;
alter system checkpoint;
rollback ;
update t2 set name=lpad('D',32,'D') where id between 5 and 9;
commit ;

alter database  datafile 6 offline ;

$ dd if=/dev/zero of=/mnt/ramdisk/book/tea01.dbf count=1 bs=8192 conv=notrunc seek=1
1+0 records in
1+0 records out
8192 bytes (8.2 kB) copied, 3.8338e-05 seconds, 214 MB/s

--//再次提醒不要忘记conv=notrunc参数,不然数据文件会被截断.我自己在以前测试中遇到这种情况!!

--//在以前rman备份的疑问中发现rman会修改块的信息,比如:
rdba_kcbh,spare3_kcbh,tailchk,当然还包括检查和.

--//拿当时备份的一个数据块分析:
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> select rowid,t1.* from t1 where id=100000;
ROWID                      ID NAME
------------------ ---------- ---------------------------------
AAAWITAAGAAAALSACM     100000 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


SCOTT@book> select count(*) from t1 where rowid between 'AAAWITAAGAAAALSAAA' and 'AAAWITAAGAAAALSBBB';
  COUNT(*)
----------
       141

SCOTT@book> @ &r/rowid AAAWITAAGAAAALSACM
    OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------
     90643          6        722        140  0x18002D2           6,722                alter system dump datafile 6 block 722 ;

--//这个块仅仅141条记录.

$ cat filelist.txt
4 /mnt/ramdisk/book/users01.dbf
1 /mnt/ramdisk/book/system01.dbf
2 /mnt/ramdisk/book/sysaux01.dbf
3 /mnt/ramdisk/book/undotbs01.dbf
5 /mnt/ramdisk/book/example01.dbf
6 /mnt/ramdisk/book/tea01.dbf
100 /home/oracle/backup/20171114_fcsji7ti_1_1

BBED> map  dba 100,723
File: /home/oracle/backup/20171114_fcsji7ti_1_1 (100)
Block: 723                                   Dba:0x190002d3
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes                      @0
struct ktbbh, 96 bytes                     @20
struct kdbh, 14 bytes                      @116
struct kdbt[1], 4 bytes                    @130
sb2 kdbr[141]                              @134
ub1 freespace[1994]                        @416
ub1 rowdata[5778]                          @2410
ub4 tailchk                                @8188

--//备份集合

BBED> set dba 100,723
        DBA             0x190002d3 (419431123 100,723)

BBED> p dba 100,723 kcbh.rdba_kcbh
ub4 rdba_kcbh                               @4        0x018002d3

BBED> p dba 100,723 kcbh.spare3_kcbh
ub2 spare3_kcbh                             @18       0x0001

BBED> p dba 100,723 tailchk
ub4 tailchk                                 @8188     0x73fd06d2


--//数据块
BBED> set dba 6,722
        DBA             0x018002d2 (25166546 6,722)

BBED> p dba 6,722 kcbh.rdba_kcbh
ub4 rdba_kcbh                               @4        0x018002d2

BBED> p dba 6,722 kcbh.spare3_kcbh
ub2 spare3_kcbh                             @18       0x0000

BBED> p dba 6,722 tailchk
ub4 tailchk                                 @8188     0x73fd0602

--//可以看出备份修改kcbh.spare3_kcbh=0x0001,rdba_kcbh修改为备份块的rdba地址,把原来rdba地址的低2位保存在tailchk.
--//我这里备份集合块与数据块差别不大,如果差距很大会出现什么情况呢?

3.继续测试:
--// drop T1,这样前面就空出一段空间没有使用,rman备份也不会备份这些块.在看看这个备份文件.
--//分析前准备:

1.记下表T2 id=1e5在那个数据块:

SCOTT@book> drop table t1 purge;
Table dropped.

SCOTT@book> select rowid,t2.* from t2 where id=1e5;
ROWID                      ID NAME
------------------ ---------- ---------------------------------
AAAWIUAAGAAAAVSACM     100000 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

SCOTT@book> @ &r/rowid AAAWIUAAGAAAAVSACM
    OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------
     90644          6       1362        140  0x1800552           6,1362               alter system dump datafile 6 block 1362

SCOTT@book> select count(*) from t2 where rowid between 'AAAWIUAAGAAAAVSAAA' and 'AAAWIUAAGAAAAVSACM';
  COUNT(*)
----------
       141
--//说明该块有141条记录.

2.使用rman备份数据文件6:

RMAN> backup  datafile 6 format '/home/oracle/backup/datafile6_20171115_%U' ;
Starting backup at 2017-11-15 15:42:38
using channel ORA_DISK_1
using channel ORA_DISK_2
using channel ORA_DISK_3
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00006 name=/mnt/ramdisk/book/tea01.dbf
channel ORA_DISK_1: starting piece 1 at 2017-11-15 15:42:38
channel ORA_DISK_1: finished piece 1 at 2017-11-15 15:42:39
piece handle=/home/oracle/backup/datafile6_20171115_fqsjku7e_1_1 tag=TAG20171115T154238 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 2017-11-15 15:42:39

Starting Control File and SPFILE Autobackup at 2017-11-15 15:42:39
piece handle=/u01/app/oracle/fast_recovery_area/BOOK/autobackup/2017_11_15/o1_mf_s_960133359_f0qvzhdt_.bkp comment=NONE
Finished Control File and SPFILE Autobackup at 2017-11-15 15:42:40

--//备份文件=/home/oracle/backup/datafile6_20171115_fqsjku7e_1_1

BBED> info
File#  Name                                                 Size(blks)
-----  ----                                                 ----------
     1  /mnt/ramdisk/book/system01.dbf                                0
     2  /mnt/ramdisk/book/sysaux01.dbf                                0
     3  /mnt/ramdisk/book/undotbs01.dbf                               0
     4  /mnt/ramdisk/book/users01.dbf                                 0
     5  /mnt/ramdisk/book/example01.dbf                               0
     6  /mnt/ramdisk/book/tea01.dbf                                   0
   206  /home/oracle/backup/datafile6_20171115_fqsjku7e_1_1           0

$ ls -l /home/oracle/backup/datafile6_20171115_fqsjku7e_1_1
-rw-r----- 1 oracle oinstall 5980160 2017-11-15 15:42:38 /home/oracle/backup/datafile6_20171115_fqsjku7e_1_1

--//备份不到6M.
--//占用5980160/8192=730块.最大块号729(从0开始记数).
--//前面测试已经说明728备份的文件头.依次往前面看.

BBED> map  dba 206,728
File: /home/oracle/backup/datafile6_20171115_fqsjku7e_1_1 (206)
Block: 728                                   Dba:0x338002d8
------------------------------------------------------------
Data File Header
struct kcvfh, 860 bytes                    @0
ub4 tailchk                                @8188

--OK,判断正确.

BBED> map  dba 206,724
File: /home/oracle/backup/datafile6_20171115_fqsjku7e_1_1 (206)
Block: 724                                   Dba:0x338002d4
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes                      @0
struct ktbbh, 96 bytes                     @20
struct kdbh, 14 bytes                      @116
struct kdbt[1], 4 bytes                    @130
sb2 kdbr[141]                              @134
ub1 freespace[1994]                        @416
ub1 rowdata[5778]                          @2410
ub4 tailchk                                @8188

BBED> set dba 206,724
        DBA             0x338002d4 (864027348 206,724)

BBED> x  /rnc   *kdbr[140] dba 206,724
rowdata[0]                                  @2410
----------
flag@2410: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2411: 0x00
cols@2412:    2

col    0[2] @2413: 100000
col   1[32] @2416: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
--//说明判断正确,就是这块.
--//备份文件中块724对于就是dba=6,1362的备份.对比备份与对于数据块的不同:

p dba 6,1362 kcbh.rdba_kcbh
p dba 6,1362 kcbh.spare3_kcbh
p dba 6,1362 tailchk

p dba 206,724 kcbh.rdba_kcbh
p dba 206,724 kcbh.spare3_kcbh
p dba 206,724 tailchk

--//数据块
BBED> p dba 6,1362 kcbh.rdba_kcbh
ub4 rdba_kcbh                               @4        0x01800552

BBED> p dba 6,1362 kcbh.spare3_kcbh
ub2 spare3_kcbh                             @18       0x0000

BBED> p dba 6,1362 tailchk
ub4 tailchk                                 @8188     0x75570602

BBED> p dba 6,1362 kcbh.chkval_kcbh
ub2 chkval_kcbh                             @16       0x30c7


--//备份集
BBED> p dba 206,724 kcbh.rdba_kcbh
ub4 rdba_kcbh                               @4        0x018005d4

BBED> p dba 206,724 kcbh.spare3_kcbh
ub2 spare3_kcbh                             @18       0x0001

BBED> p dba 206,724 tailchk
ub4 tailchk                                 @8188     0x75570652

BBED> p dba 206,724 kcbh.chkval_kcbh
ub2 chkval_kcbh                             @16       0x3010

--//kcbh.spare3_kcbh 从 0x0000 => 0x0001.
--724=0x2d4
--1362=0x552

--//注意看原数据块 kcbh.rdba_kcbh=0x01800552 备份后变成了 kcbh.rdba_kcbh= 0x018005d4.
--//也就是将数据块的dba地址的低2位0x52保存到tailchk的低2位.
--//同时将备份时数据块的kcbh.rdba_kcbh的低2位0x52 变成备份块的块地址的低2位(前面0x02丢弃了)0xd4.
--//当然这样检查和也会发生变化.

--//将变化的低2位做异或操作.

$ echo 52 00 02 c7 d4 01 52 |xor.sh
52
00
02
C7
D4
01
52
xor result: 10

$ echo 0552 0000 0602 30c7 05d4 0001 0652 |xor.sh
0552
0000
0602
30C7
05D4
0001
0652
xor result: 3010

--//正好是备份对应块检查和的低2位.(dba 206,724 kcbh.chkval_kcbh=0x3010)
--//感觉自己好无聊^_^,放弃不再探究了.

--//关于做异或的脚本可以参考如下链接:
http://blog.itpub.net/267265/viewspace-2134945/