暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

TRUNCATE TABLE恢复系列三:终极大招,BBED修改元数据恢复被TRUNCATE的表

Oracle恢复实录 2020-02-04
2321

点击上方蓝字关注我们,文末有惊喜~




我们的文章会在微信公众号“Oracle恢复实录”和博客网站“rescureora.com” 同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!


今天是2020年02月04日,二十四节气之一的立春。桃花春水渌,水上鸳鸯浴。本将是一片明丽的春色,一派盎然的春意,然而今年“不速之客”新型冠状病毒的突如其来,虽猝不及防,但是坚信我们能打赢这场病毒保卫战。万众一心除疫患,众志成城送瘟神!

没有一个冬天不可逾越,没有一个春天不会来临。无论2020开头多么艰难,相信阳光终会到来。

在这众志成城送瘟神日子里,很多小伙伴也陆续返回到工作地点,以远程办公或者轮流值班的方式开始新的一年工作,也祝大家在新的一年里工作顺利,事业有成。我们的博客也带来了最新的一篇《TRUNCATE TABLE恢复系列三:终极大招,BBED修改元数据恢复被TRUNCATE的表》。同时预告下期我们会推出TRUNCATE TABLE恢复系列四:利用ODU快速恢复被TRUNCATE的表。

在第一篇《 TRUNCATE TABLE恢复系列一:深层剖析内部原理 》(点击标题可直达原文)中说到:truncate的实质是在不修改数据块的情况下,通过修改segment header的data_object_id、hwm、extent map、aux map等信息来实现清空表的目的,其中还涉及数据字典基表以及L1、L2位图块的修改。

那么对于使用bbed修复元数据的方式去恢复,首先需要确认哪些元数据块和数据字典是需要恢复的呢?通过10046跟踪我们可以发现,全表扫描查询一定会访问segment header,但是不会去访问任何L1、L2位图块的,访问的数据字典基表包括user$、obj$、tab$、tab_stats$、ts$、seg$、ind$、ind_stats$、col$、objauth$、cdef$、histgrm$、hist_head$,这里重点关注通过10046跟踪truncate操作有更改的基表obj$、tab$、seg$、tab_stats$(统计信息不用管),其中seg$经过测试只要block#,file#,ts#不被更改就无需理会,而truncate操作是不会修改seg$的ts#、file#、block#的。

接下来,我们一起看具体的测试过程:

所以需要恢复的元数据块和数据字典基表以及内容为:
  • segment header(dataobj#,LHWM,HHWM,extent map,aux map以及extents个数)

  • tab$(dataobj#)

  • obj$(dataobj#)

下面提供segment header的信息对应的offset:

segment header dump:
Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 28     #blocks: 1664  
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater:: 0x01405b83  ext#: 27     blk#: 3      ext size: 128   
  #blocks in seg. hdr's freelists: 0 
  #blocks below: 1539 
  mapblk 0x00000000 offset: 27 
                   Unlocked
  --------------------------------------------------------
  Low HighWater Mark : 
      Highwater:: 0x01405b83 ext#: 27 blk#: 3 ext size: 128 
  #blocks in seg. hdr'
s freelists: 0     
  #blocks below: 1539  
  mapblk 0x00000000  offset: 27    
  Level 1 BMB for High HWM block: 0x01405b80
  Level 1 BMB for Low HWM block: 0x01405b80
  --------------------------------------------------------
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0      
  L2 Array start offset: 0x00001434
  First Level 3 BMB: 0x00000000
  L2 Hint for inserts: 0x01400769
  Last Level 1 BMB: 0x01405b81
  Last Level II BMB: 0x01400769
  Last Level III BMB: 0x00000000
     Map Header:: next 0x00000000  #extents: 28   obj#: 16840  flag: 0x10000000
  Inc # 0 
  Extent Map
  -----------------------------------------------------------------
   0x01400768  length: 8     
   0x01402f48 length: 8     
   0x01402f50 length: 8     
   0x01402f58 length: 8     
   0x01402f60 length: 8     
   0x01402f68 length: 8     
   0x01402f70 length: 8     
   0x01402f78 length: 8     
   0x01402e80  length: 8     
   0x01402e88  length: 8     
   0x01402e90  length: 8     
   0x01402e98  length: 8     
   0x01402ea0  length: 8     
   0x01402ea8  length: 8     
   0x01402eb0  length: 8     
   0x01402eb8  length: 8     
   0x01403f80 length: 128   
   0x01404000  length: 128   
   0x01404080  length: 128   
   0x01404180  length: 128   
   0x01405800  length: 128   
   0x01405880  length: 128   
   0x01405900  length: 128   
   0x01405980  length: 128   
   0x01405a00  length: 128   
   0x01405a80  length: 128   
   0x01405b00  length: 128   
   0x01405b80  length: 128   
  
  Auxillary Map
  --------------------------------------------------------
   Extent 0     : L1 dba: 0x01400768 Data dba: 0x0140076b
   Extent 1     : L1 dba: 0x01400768 Data dba: 0x01402f48
   Extent 2     : L1 dba: 0x01402f50 Data dba: 0x01402f51
   Extent 3     : L1 dba: 0x01402f50 Data dba: 0x01402f58
   Extent 4     : L1 dba: 0x01402f60 Data dba: 0x01402f61
   Extent 5     : L1 dba: 0x01402f60 Data dba: 0x01402f68
   Extent 6     : L1 dba: 0x01402f70 Data dba: 0x01402f71
   Extent 7     : L1 dba: 0x01402f70 Data dba: 0x01402f78
   Extent 8     : L1 dba: 0x01402e80 Data dba: 0x01402e81
   Extent 9     : L1 dba: 0x01402e80 Data dba: 0x01402e88
   Extent 10    : L1 dba: 0x01402e90 Data dba: 0x01402e91
   Extent 11    : L1 dba: 0x01402e90 Data dba: 0x01402e98
   Extent 12    : L1 dba: 0x01402ea0 Data dba: 0x01402ea1
   Extent 13    : L1 dba: 0x01402ea0 Data dba: 0x01402ea8
   Extent 14    : L1 dba: 0x01402eb0 Data dba: 0x01402eb1
   Extent 15    : L1 dba: 0x01402eb0 Data dba: 0x01402eb8
   Extent 16    : L1 dba: 0x01403f80 Data dba: 0x01403f82
   Extent 17    : L1 dba: 0x01404000 Data dba: 0x01404002
   Extent 18    : L1 dba: 0x01404080 Data dba: 0x01404082
   Extent 19    : L1 dba: 0x01404180 Data dba: 0x01404182
   Extent 20    : L1 dba: 0x01405800 Data dba: 0x01405802
   Extent 21    : L1 dba: 0x01405880 Data dba: 0x01405882
   Extent 22    : L1 dba: 0x01405900 Data dba: 0x01405902
   Extent 23    : L1 dba: 0x01405980 Data dba: 0x01405982
   Extent 24    : L1 dba: 0x01405a00 Data dba: 0x01405a02
   Extent 25    : L1 dba: 0x01405a80 Data dba: 0x01405a82
   Extent 26    : L1 dba: 0x01405b00 Data dba: 0x01405b02
   Extent 27    : L1 dba: 0x01405b80 Data dba: 0x01405b82
  --------------------------------------------------------
  
   Second Level Bitmap block DBAs 
   --------------------------------------------------------
   DBA 10x01400769

复制

下面是比较重要的segment header每个offset对应的含义:

确认了需要恢复的内容之后,还需要确认是否有对象占用了truncate释放的空间,判断依据是用从redo dump找到的truncate前的extent map和dba_extents对比。如果有对象占用需要先move对象到其他表空间。如何从redo dump找到extent map后面段头块的extent map恢复。






无覆盖的TRUNCATE恢复





假如确实发生了truncate table误操作,需要马上停应用,最好将表空间设置为offline或者read only,避免数据被覆盖。

通过之前对table full scan、segment header和前面truncate原理的分析,tfs不会读取L1,L2块,所以恢复的时候L1,L2块和具体存放数据的块都不用管,只需尝试通过修改段头块和基表信息来恢复truncate的数据,bbed修改段头块的具体offset含义见segment header章节。


 


修改段头块dataobj#




由于表可能不止一次被truncate,所以获取之前dataobj#最好的办法是通过logminer或者redo dump,这里我们使用的是redo dump。

REDO RECORD - Thread:1 RBA: 0x000055.0000001b.0080 LEN: 0x00ac VLD: 0x01
SCN: 0x0000.003ed056 SUBSCN: 1 04/21/2018 12:25:34
CHANGE #1 TYP:0 CLS:34 AFN:6 DBA:0x018002ee OBJ:4294967295 SCN:0x0000.003ed054 SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 64 spc: 822 flg: 0x0022 seq: 0x017b rec: 0x33
            xid: 0x0009.00f.00000353  
ktubu redo: slt: 15 rci: 50 opc: 14.5 objn: 1 objd: 16840 tsn: 5
Undo type: Regular undo       Undo typeLast buffer splitNo 
Tablespace Undo: Yes
             0x00000000
kteopu undo - undo operation on extent map
       segdba: 0x140076a  class4  mapdba:0x140076a  offset2
 rbr extent - dba: 0x0  nbk: 0x0
kteop redo - redo operation on extent map
   CDOBJ: new object number:16840
CHANGE #2 TYP:0 CLS:4 AFN:5 DBA:0x0140076a OBJ:16840 SCN:0x0000.003ed050 SEQ:2 OP:14.4 ENC:0 RBL:0
kteop redo - redo operation on extent map
   CDOBJ: new object number:16860

复制
从redo dump信息可以看到段头块0x0140076a的dataobj#从16840变成了16860,所以这里需要将段头块的dataobj#改回16840。

仅仅修改段头块的dataobj#再次查询表会报ORA-08103: object no longer exists,原因是基表没有修改。查询的时候会通过表名去找到该表的dataobj#。


 


恢复段头块HWM



HWM信息可以从redo dump中获取:

REDO RECORD - Thread:1 RBA: 0x000055.00000016.0148 LEN: 0x01b8 VLD: 0x01
SCN: 0x0000.003ed050 SUBSCN: 5 04/21/2018 12:25:34
CHANGE #1 TYP:0 CLS:34 AFN:6 DBA:0x018002ee OBJ:4294967295 SCN:0x0000.003ed050 SEQ:3 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 164 spc: 1112 flg: 0x0022 seq: 0x017b rec: 0x30
            xid: 0x0009.00f.00000353  
ktubu redo: slt: 15 rci: 47 opc: 13.29 objn: 16840 objd: 16840 tsn: 5
Undo type: Regular undo       Undo typeLast buffer splitNo 
Tablespace UndoNo 
             0x00000000
Segment Header Undo
Seghdr dba: 0x0140076a Mapblock dba: 0x00000000 Mapredo Offset4 scls: 4 mcls: 140733193388039
Both the HWMs
Low HWM
      Highwater:: 0x01405b83  ext#: 27     blk#: 3      ext size128   
  #blocks in seg. hdr's freelists: 0
  #blocks below: 1539
  mapblk 0x00000000 offset: 27
lfdba: 0x01405b80
High HWM
      Highwater:: 0x01405b83 ext#: 27 blk#: 3 ext size: 128
  #blocks in seg. hdr'
freelists0     
  #blocks below: 1539  
  mapblk 0x00000000  offset27    
lfdba: 0x01405b80 hint dba: 0x01400769
Lasts in Header
LF: 20994945 LS: 20973417 LT: 0 FT: 0
CHANGE #2 TYP:0 CLS:4 AFN:5 DBA:0x0140076a OBJ:16840 SCN:0x0000.003ed050 SEQ:1 OP:13.28 ENC:0 RBL:0
Both the HWMs
Low HWM
      Highwater:: 0x0140076b  ext#: 0      blk#: 3      ext size8     
  #blocks in seg. hdr's freelists: 0
  #blocks below: 0
  mapblk 0x00000000 offset: 0
lfdba: 0x01400768
High HWM
      Highwater:: 0x0140076b ext#: 0 blk#: 3 ext size: 8
  #blocks in seg. hdr'
freelists0     
  #blocks below: 0     
  mapblk 0x00000000  offset0     
lfdba: 0x01400768 hint dba: 0x01400769
Lasts in Header
LF: 20973416 LS: 20973417 LT: 0 FT: 0
CHANGE #3 TYP:0 CLS:8 AFN:5 DBA:0x01400768 OBJ:16840 SCN:0x0000.003ed050 SEQ:2 OP:13.22 ENC:0 RBL:0
Redo on Level1 Bitmap Block
Redo to set hwm
Opcode: 32      Highwater:: 0x0140076b  ext#: 0      blk#: 3      ext size8     
  #blocks in seg. hdr's freelists: 0
  #blocks below: 0
  mapblk 0x00000000 offset: 0

复制
可以看到段头块0x0140076a的LHWM信息和HHWM是一样的,都是从

Highwater::  0x01405b83  ext#: 27     blk#: 3      ext size: 128

变成了

Highwater::  0x0140076b  ext#: 0      blk#: 3      ext size: 8

所以这里恢复HWM信息只需要根据redo dump改回去即可。


 


恢复段头块extent map,Auxillary Map以及extent个数





extent信息和aux map信息同样可以从redo dump中获取:

REDO RECORD - Thread:1 RBA: 0x000055.00000027.0180 LEN: 0x0138 VLD: 0x01
SCN: 0x0000.003ed061 SUBSCN: 3 04/21/2018 12:25:35
CHANGE #1 TYP:0 CLS:17 AFN:6 DBA:0x01800120 OBJ:4294967295 SCN:0x0000.003ed061 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0014 sqn: 0x00000000 flg: 0x0002 siz: 112 fbi: 248
            uba: 0x018006ea.018c.1f pxid: 0x0000.000.00000000
CHANGE #2 TYP:0 CLS:18 AFN:6 DBA:0x018006ea OBJ:4294967295 SCN:0x0000.003ed061 SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 112 spc: 3358 flg: 0x0022 seq: 0x018c rec: 0x1f
            xid: 0x0001.014.00000297  
ktubu redo: slt: 20 rci: 0 opc: 14.5 objn: 1 objd: 16860 tsn: 5
Undo type: Regular undo       Undo typeLast buffer splitNo 
Tablespace Undo: Yes
             0x00000000
kteopu undo - undo operation on extent map
       segdba: 0x140076a  class4  mapdba:0x140076a  offset3
 rbr extent - dba: 0x0  nbk: 0x0
kteop redo - redo operation on extent map
   ADD: dba:0x1405b80 len:128 at offset:27 --truncate前的extent信息
  ADDAXT: offset:27 fdba:x01405b80 bdba:0x01405b82 --truncate前的aux map信息
   SETSTAT: exts:28 blks:1664 lastmap:0x0 mapcnt:0
CHANGE #3 TYP:0 CLS:4 AFN:5 DBA:0x0140076a OBJ:16860 SCN:0x0000.003ed061 SEQ:2 OP:14.4 ENC:0 RBL:0
kteop redo - redo operation on extent map
   DELETE: entry:27
   shift back: dba:0x0 len:0 
   SETSTAT: exts:27 blks:1536 lastmap:0x0 mapcnt:0

复制
从redo dump可以发现truncate操作对于extent map和aux map是从最后一个extent开始逐一删除的,这里可以看到该表的extent总共有28个,ext#为27是该表最后一个extent,block_id为0x1405b80,该extent size为128个块,以此类推很容易可以通过简单的grep找出extent map;同理ext#为27的aux map的L1 dba为x01405b80,data dba为0x01405b82,以此类推很容易可以通过简单的grep找出aux map。
extent map:
[root@rescureora ~]# grep -i "ADD: dba" /u01/app/oracle/diag/rdbms/rescureora/rescureora/trace/rescureora_ora_7611.trc
   ADD: dba:0x1405b80 len:128 at offset:27
   ADD: dba:0x1405b00 len:128 at offset:26
   ADD: dba:0x1405a80 len:128 at offset:25
   ADD: dba:0x1405a00 len:128 at offset:24
   ADD: dba:0x1405980 len:128 at offset:23
   ADD: dba:0x1405900 len:128 at offset:22
   ADD: dba:0x1405880 len:128 at offset:21
   ADD: dba:0x1405800 len:128 at offset:20
   ADD: dba:0x1404180 len:128 at offset:19
   ADD: dba:0x1404080 len:128 at offset:18
   ADD: dba:0x1404000 len:128 at offset:17
   ADD: dba:0x1403f80 len:128 at offset:16
   ADD: dba:0x1402eb8 len:8 at offset:15
   ADD: dba:0x1402eb0 len:8 at offset:14
   ADD: dba:0x1402ea8 len:8 at offset:13
   ADD: dba:0x1402ea0 len:8 at offset:12
   ADD: dba:0x1402e98 len:8 at offset:11
   ADD: dba:0x1402e90 len:8 at offset:10
   ADD: dba:0x1402e88 len:8 at offset:9
   ADD: dba:0x1402e80 len:8 at offset:8
   ADD: dba:0x1402f78 len:8 at offset:7
   ADD: dba:0x1402f70 len:8 at offset:6
   ADD: dba:0x1402f68 len:8 at offset:5
   ADD: dba:0x1402f60 len:8 at offset:4
   ADD: dba:0x1402f58 len:8 at offset:3
   ADD: dba:0x1402f50 len:8 at offset:2
   ADD: dba:0x1402f48 len:8 at offset:1

aux map:
[root@rescureora ~]# grep -i "ADDAXT:" /u01/app/oracle/diag/rdbms/rescureora/rescureora/trace/rescureora_ora_7611.trc
  ADDAXT: offset:27 fdba:x01405b80 bdba:0x01405b82
  ADDAXT: offset:26 fdba:x01405b00 bdba:0x01405b02
  ADDAXT: offset:25 fdba:x01405a80 bdba:0x01405a82
  ADDAXT: offset:24 fdba:x01405a00 bdba:0x01405a02
  ADDAXT: offset:23 fdba:x01405980 bdba:0x01405982
  ADDAXT: offset:22 fdba:x01405900 bdba:0x01405902
  ADDAXT: offset:21 fdba:x01405880 bdba:0x01405882
  ADDAXT: offset:20 fdba:x01405800 bdba:0x01405802
  ADDAXT: offset:19 fdba:x01404180 bdba:0x01404182
  ADDAXT: offset:18 fdba:x01404080 bdba:0x01404082
  ADDAXT: offset:17 fdba:x01404000 bdba:0x01404002
  ADDAXT: offset:16 fdba:x01403f80 bdba:0x01403f82
  ADDAXT: offset:15 fdba:x01402eb0 bdba:0x01402eb8
  ADDAXT: offset:14 fdba:x01402eb0 bdba:0x01402eb1
  ADDAXT: offset:13 fdba:x01402ea0 bdba:0x01402ea8
  ADDAXT: offset:12 fdba:x01402ea0 bdba:0x01402ea1
  ADDAXT: offset:11 fdba:x01402e90 bdba:0x01402e98
  ADDAXT: offset:10 fdba:x01402e90 bdba:0x01402e91
  ADDAXT: offset:9 fdba:x01402e80 bdba:0x01402e88
  ADDAXT: offset:8 fdba:x01402e80 bdba:0x01402e81
  ADDAXT: offset:7 fdba:x01402f70 bdba:0x01402f78
  ADDAXT: offset:6 fdba:x01402f70 bdba:0x01402f71
  ADDAXT: offset:5 fdba:x01402f60 bdba:0x01402f68
  ADDAXT: offset:4 fdba:x01402f60 bdba:0x01402f61
  ADDAXT: offset:3 fdba:x01402f50 bdba:0x01402f58
  ADDAXT: offset:2 fdba:x01402f50 bdba:0x01402f51
  ADDAXT: offset:1 fdba:x01400768 bdba:0x01402f48
复制
这里可以写脚本根据segment header章节offset的含义来生成bbed命令,由于bbed命令较长省略一部分。

bbed修改后extent map恢复成功:

复制
BBED> d v offset 280
 File: u01/app/oracle/oradata/test/users01.dbf (4)
 Block: 1898    Offsets:  280 to  579  Dba:0x0100076a
-------------------------------------------------------
 68074001 08000000 482f4001 08000000 l h.@.....H/@.....
 502f4001 08000000 582f4001 08000000 l P/@.....X/@.....
 602f4001 08000000 682f4001 08000000 l `/@.....h/@.....
 702f4001 08000000 782f4001 08000000 l p/@.....x/@.....
 802e4001 08000000 882e4001 08000000 l ..@.......@.....
 902e4001 08000000 982e4001 08000000 l ..@.......@.....
 a02e4001 08000000 a82e4001 08000000 l ..@.......@.....
 b02e4001 08000000 b82e4001 08000000 l ..@.......@.....
 803f4001 80000000 00404001 80000000 l .?@......@@.....
 80404001 80000000 80414001 80000000 l .@@......A@.....
 00584001 80000000 80584001 80000000 l .X@......X@.....
 00594001 80000000 80594001 80000000 l .Y@......Y@.....
 005a4001 80000000 805a4001 80000000 l .Z@......Z@.....
 005b4001 80000000 805b4001 80000000 l .[@......[@.....
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000          l ............

 <16 bytes per line>

aux map恢复成功:
BBED> d v offset 2736
 File: u01/app/oracle/oradata/test/users01.dbf (4)
 Block: 1898    Offsets: 2736 to 3035  Dba:0x0100076a
-------------------------------------------------------
 68074001 6b074001 68074001 482f4001 l h.@.k.@.h.@.H/@.
 502f4001 512f4001 502f4001 582f4001 l P/@.Q/@.P/@.X/@.
 602f4001 612f4001 602f4001 682f4001 l `/@.a/@.`/@.h/@.
 702f4001 712f4001 702f4001 782f4001 l p/@.q/@.p/@.x/@.
 802e4001 812e4001 802e4001 882e4001 l ..@...@...@...@.
 902e4001 912e4001 902e4001 982e4001 l ..@...@...@...@.
 a02e4001 a12e4001 a02e4001 a82e4001 l ..@...@...@...@.
 b02e4001 b12e4001 b02e4001 b82e4001 l ..@...@...@...@.
 803f4001 823f4001 00404001 02404001 l .?@..?@..@@..@@.
 80404001 82404001 80414001 82414001 l .@@..@@..A@..A@.
 00584001 02584001 80584001 82584001 l .X@..X@..X@..X@.
 00594001 02594001 80594001 82594001 l .Y@..Y@..Y@..Y@.
 005a4001 025a4001 805a4001 825a4001 l .Z@..Z@..Z@..Z@.
 005b4001 025b4001 805b4001 825b4001 l .[@..[@..[@..[@.
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000          l ............

 <16 bytes per line>

复制


 


恢复成功




这里由于L1,L2没有恢复,所以insert会有问题,但是可以通过CTAS重建表完全恢复。






被覆盖的truncate恢复





上面的恢复方式只适用于truncate的数据没有被覆盖,也就是没有其他对象占用了truncate所释放的空间。所以在操作时需要查询dba_extents对比redo dump出来的extent map,如果没有覆盖的情况,则上述方法可行。那么被覆盖的情况该如何处理呢?


 


建立测试环境





创建测试环境:

在这里就可以清楚的发现表truncate_table_2的数据被表aaa覆盖了一部分。


 


将占用truncate释放的空间的对象move到其他表空间





move之前先查询该对象占用的extent信息,并且dump segment header以便后续的处理。
SYS@:>select extent_id,file_id,block_id,blocks from dba_extents where segment_name='AAA';

 EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
         0 4 144 8
         1 4 152 8

SYS@:>alter table rescureora.aaa move tablespace users;

Table altered.

复制


 


恢复段头块以及数据字典信息





这里步骤和没有覆盖情况一致,所以稍微简略一些。

尝试查询报错:
SYS@RESCUREORA(rescureora):1>select count(*from rescureora.truncate_table_2;
select count(*from rescureora.truncate_table_2
                          *
ERROR at line 1:
ORA-08103: object no longer exists

复制

剩下的便是解决8103的问题了,实际上出现8103错误就是被覆盖的数据块的dataobj#和truncate_table_2的dataobj#不一致导致的。

Corrupt block relative dba: 0x01000090 (file 4, block 144)
Fractured block found during multiblock buffer read
Data in bad block:
 type: 6 format: 2 rdba: 0x01000090
 last change scn: 0x0000.003f9e3d seq: 0x3 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x9e3d2003
 check value in block header: 0x5bde
 computed block checksum: 0x0
Reading datafile '/u01/app/oracle/oradata/rescureora/RESCUREORA/datafile/o1_mf_test_fg6gjt1d_.dbf' for corruption at rdba: 0x01000090 (file 4, block 144)
Reread (file 4, block 144) found same corrupt data (no logical check)

*** SESSION ID:(178.85) 2018-04-28 00:24:12.968
OBJD MISMATCH typ=33, seg.obj=16958, diskobj=16960, dsflg=100001, dsobj=16958, tid=16958, cls=1

复制
明确指出在全表扫描的时候发现file 4 block 144的dataobj#为16960,但是seg的dataobj#为16958。




确认具体哪些块被覆盖





表AAA在move之前,需要先查出extent信息和dump segment header,目的就在这里(假如没有dump 段头仍然可以从redo dump里找到HWM信息)。
extent 信息
SYS@:>select extent_id,file_id,block_id,blocks from dba_extents where segment_name='AAA';

 EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
         0          4        144          8
         1          4        152          8
可以确定4号文件144号块开始被覆盖,但是不一定ext#为1的最后一个块也被覆盖了,因为LHWM和HHWM之间的块不一定被覆盖

HWM信息
Highwater:: 0x0100009a  ext#: 1 blk#: 2 ext size: 8 --file 4 block 154

复制




解决ORA-8103





构造rowid绕过dataobj#不匹配的块:

成功挽救5303条数据,少了697条,也可以用dbms_repair标记这些块为坏块,然后跳过这些块。

注:本文示例为恢复非分区非lob表,分区表和含lob表在原理上可以恢复,但过程较为繁琐。下期我们将推出更为简便的工具篇,敬请期待!



福利



我们将陆续为大家提供 linux 操作系统 rhel镜像的下载地址。请扫码图片二维码关注我们的公众号,并在后台回复关键词: “ rhel + 版本数 ”,如:rhel7.7 等,快来一起下载吧~!


 
往期回顾


Oracle恢复实录

rescureora.com

欢迎扫码关注



最后修改时间:2020-02-10 11:17:55
文章转载自Oracle恢复实录,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论