表刪除恢復腳本(bbed腳本恢復刪除的表數據)

    數據庫沒有備份、也沒有歸檔,數據被誤刪除了,如果這個時候存放數據的數據塊還沒有被重用,那麼可以通過bbed批量修改數據庫塊,把誤刪的數據找回。

測試如下:

1、創建一個測試表TEST

SQL> create table test as select level lv, dbms_random.string('l',20)  name from dual connect by level < 10000;

Table created.

SQL> 

2、查詢表TEST對應的表空間和object_id號


SQL> 
SQL> select object_id, object_name, owner from dba_objects where object_name = 'TEST' and owner = 'SCOTT';

 OBJECT_ID OBJECT_NAME                                        OWNER
---------- -------------------------------------------------  ------------------------------
    136220 TEST                                               SCOTT

SQL> 
SQL> col file_name for a50
SQL> select file_name,file_id  from dba_data_files where tablespace_name = 'USERS';

FILE_NAME                                             FILE_ID
-------------------------------------------------- ----------
/u01/app/oradata/QXY/users01.dbf                            4

SQL> 

3、查看刪除之前表TEST的數據分佈信息

SQL> select distinct dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) from test order by 2 asc;

DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------ ------------------------------------
                                   4                                  811
                                   4                                  812
                                   4                                  813
                                   4                                  814
                                   4                                  815
                                   4                                 1232
                                   4                                 1233
                                   4                                 1234
                                   4                                 1235
                                   4                                 1236
                                   4                                 1237
                                   4                                 1238
                                   4                                 1239
                                   4                                 1241
                                   4                                 1242
                                   4                                 1243
                                   4                                 1244
                                   4                                 1245
                                   4                                 1246
                                   4                                 1247
                                   4                                10488
                                   4                                10489
                                   4                                10490
                                   4                                10491
                                   4                                10492
                                   4                                10493
                                   4                                10494
                                   4                                10495
                                   4                                10569
                                   4                                10570
                                   4                                10571
                                   4                                10572
                                   4                                10573
                                   4                                10574
                                   4                                10575
                                   4                                10576
                                   4                                10577
                                   4                                10578
                                   4                                10579
                                   4                                10580
                                   4                                10581
                                   4                                10582

42 rows selected.


SQL> 

4、抽取TEST表的第一個塊(811塊),查看刪除之前的內容

SQL> alter system dump datafile 4 block 811;

System altered.


11 rows selected.

SQL> select value from v$diag_info where name ='Default Trace File';

VALUE
--------------------------------------------------------------
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_2631.trc

SQL> 

data_block_dump,data header at 0x7ff415a3107c
===============
tsiz: 0x1f80
hsiz: 0x1fa
pbl: 0x7ff415a3107c
     76543210
flag=--------
ntab=1
nrow=244    <====811塊有244行數據
frre=-1
fsbo=0x1fa
fseo=0x535

   <=======中間內容省略

block_row_dump:
tab 0, row 0, @0x1f65
tl: 27 fb: --H-FL-- lb: 0x0  cc: 2    <=====塊沒有被刪除之前,標誌位--H-FL--
col  0: [ 2]  c1 02
col  1: [20]  6f 7a 67 71 6d 79 62 76 77 69 64 70 74 67 66 6b 78 64 73 7a
tab 0, row 1, @0x1f4a
tl: 27 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 03
col  1: [20]  75 74 6a 61 74 79 64 6a 74 6b 75 6c 6a 62 68 6a 76 65 71 79
tab 0, row 2, @0x1f2f
tl: 27 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 04
col  1: [20]  6b 79 66 6f 7a 64 70 69 71 73 6b 61 69 71 62 68 79 6b 61 67
tab 0, row 3, @0x1f14
tl: 27 fb: --H-FL-- lb: 0x0  cc: 2


塊沒有被刪除之前,標誌位--H-FL--  32+8+4 = 44 轉換成16進製爲2c

通過bbed查看刪除之前的塊

BBED>  set dba 4,811
        DBA             0x0100032b (16778027 4,811)


BBED> p
ktbbh.ktbbhtyp
--------------
ub1 ktbbhtyp                                @20       0x01 (KDDBTDATA)

BBED> map 
 File: /u01/app/oradata/QXY/users01.dbf (4)
 Block: 811                                   Dba:0x0100032b
------------------------------------------------------------
 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0       

 struct ktbbh, 96 bytes                     @20      

 struct kdbh, 14 bytes                      @124     

 struct kdbt[1], 4 bytes                    @138     

 sb2 kdbr[244]                              @142      <====該塊有244行數據

 ub1 freespace[827]                         @630     

 ub1 rowdata[6731]                          @1457    

 ub4 tailchk                                @8188    


BBED> p kdbt
struct kdbt[0], 4 bytes                     @138     
   sb2 kdbtoffs                             @138      0
   sb2 kdbtnrow                             @140      244

BBED> p *kdbr[1]
rowdata[6677]
-------------
ub1 rowdata[6677]                           @8134     0x2c

BBED> x /rnc *kdbr[1]
rowdata[6677]                               @8134    
-------------
flag@8134: 0x2c (KDRHFL, KDRHFF, KDRHFH)        <======可以看到沒有這個標誌的16進制是2c
lock@8135: 0x00
cols@8136:    2

col    0[2] @8137: 2                                   <==並且可以看到該行數據的內容
col   1[20] @8140: utjatydjtkuljbhjveqy


BBED> 

<=====kdbr[1]代表這個塊的第二行數據,kdbr[0]代表第一行。查看的信息和bbed看到的一樣
SQL> select * from test where lv=2;

        LV NAME
---------- -----------------------------
         2 utjatydjtkuljbhjveqy

5、刪除TEST表數據

SQL> delete test;

9999 rows deleted.

SQL> commit;

Commit complete.

SQL> alter system flush buffer_cache;

System altered.

SQL> 

6、查看刪除之後TEST表數據的內容

<=====再次dump4文件的811內容
data_block_dump,data header at 0x7fba267f5a7c
===============
tsiz: 0x1f80
hsiz: 0x1fa
pbl: 0x7fba267f5a7c
     76543210
flag=--------
ntab=1
nrow=244
frre=-1
fsbo=0x1fa
fseo=0x36b
avsp=0x33b
tosp=0x1d86


0x1f8:pri[243]  offs=0x1c2e
block_row_dump:
tab 0, row 0, @0x36b
tl: 2 fb: --HDFL-- lb: 0x2   <======該標誌位從原來的--H-FL--變成了--HDFL--, 其中D就代表刪除的意思
tab 0, row 1, @0x386
tl: 2 fb: --HDFL-- lb: 0x2
tab 0, row 2, @0x3a1
tl: 2 fb: --HDFL-- lb: 0x2
tab 0, row 3, @0x3bc
tl: 2 fb: --HDFL-- lb: 0x2
tab 0, row 4, @0x3d7
tl: 2 fb: --HDFL-- lb: 0x2
tab 0, row 5, @0x3f2


通過bbed查看刪除之後的kdbr[1]

BBED> set dba 4,811
        DBA             0x0100032b (16778027 4,811)

BBED> map 
 File: /u01/app/oradata/QXY/users01.dbf (4)
 Block: 811                                   Dba:0x0100032b
------------------------------------------------------------
 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0       

 struct ktbbh, 96 bytes                     @20      

 struct kdbh, 14 bytes                      @124     

 struct kdbt[1], 4 bytes                    @138     

 sb2 kdbr[244]                              @142     

 ub1 freespace[369]                         @630     

 ub1 rowdata[7189]                          @999     

 ub4 tailchk                                @8188    

BBED> 
BBED> x /rnc *kdbr[1]
rowdata[6677]                               @8134    
-------------
flag@8134: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)        <====多了一個KDRHFD。且看不到之前的數據
lock@8135: 0x02
cols@8136:    0

BBED> 

7、表已經被刪除了,首先需要找到表TEST對應的數據塊有哪些

表sid的信息是存放在塊的ktbbh.ktbbhsid.ktbbhod1 這個位置,如下:

BBED> p ktbbh
struct ktbbh, 96 bytes                      @20      
   ub1 ktbbhtyp                             @20       0x01 (KDDBTDATA)
   union ktbbhsid, 4 bytes                  @24      
      ub4 ktbbhsg1                          @24       0x0002141c   <=====代表sid
      ub4 ktbbhod1                          @24       0x0002141c
   struct ktbbhcsc, 8 bytes                 @28      
      ub4 kscnbas                           @28       0x022f767a
      ub2 kscnwrp                           @32       0x0000
      
BBED> p /d dba 4,811  ktbbh.ktbbhsid.ktbbhod1     <=====10進制打印,可以看到sid= 136220即表TEST的sid
ub4 ktbbhod1                                @24       136220

BBED> 

 

SQL> select object_id, object_name, owner from dba_objects where object_name = 'TEST' and owner = 'SCOTT';

 OBJECT_ID OBJECT_NAME                                        OWNER
---------- -------------------------------------------------  ------------------------------
    136220 TEST                                               SCOTT

SQL> 


8、找表TEST所在的塊信息

cat>sandata.sh
#!/bin/sh
. ~/.bash_profile
for ((i=1; i<=15000; i ++))    //i的長度取決於文件的大小
do
        objectid=`echo p /d dba 4,$i ktbbh.ktbbhsid.ktbbhod1 | bbed | grep 'ktbbhod1' | awk '{print $5}'`
        if [ "$objectid" = "136220" ];then
                echo $i;
        fi;
done

運行結果如下:

[oracle@QXY ~]$ ./scandata.sh > sh.out
[oracle@QXY ~]$ cat sh.out 
811
812
813
814
815
1232
1233
1234
1235
1236
1237
1238
1239
1241
1242
1243
1244
1245
1246
1247
10488
10489
10490
10491
10492
10493
10494
10495
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
[oracle@QXY ~]$ 

可以看到,得到的結果和第三步看到的數據一致,也就是說這些塊包括了SID=136220。

9、修改第八步得到的塊信息,就是把行數據的0x3c修改成0x2c(--HDFL--修改成--H-FL--) 

#!/bin/sh
. ~/.bash_profile
cat sh.out | while read i
   do
        len=`echo p /d dba 4,$i offset 0 kdbt[0] | bbed | grep 'kdbtnrow' | awk '{print $4}'`
        if [ -n "$len" ];then
        for ((j=0; j<$len; j++))
        do
                offset=`echo p dba 4, $i *kdbr[$j]| bbed | grep '^ub1*.*rowdata' | awk '{print $3}' |sed 's/@//g'`
                echo "assign /x dba 4, $i offset $offset = 0x2c"
        done
        fi
        echo "sum apply dba 4,$i"
done

運行結果如下:

assign /x dba 4, 811 offset 8161 = 0x2c    <====每一行代表一行數據
assign /x dba 4, 811 offset 8134 = 0x2c
assign /x dba 4, 811 offset 8107 = 0x2c
assign /x dba 4, 811 offset 8080 = 0x2c
assign /x dba 4, 811 offset 8053 = 0x2c
assign /x dba 4, 811 offset 8026 = 0x2c
assign /x dba 4, 811 offset 7999 = 0x2c
assign /x dba 4, 811 offset 7972 = 0x2c
assign /x dba 4, 811 offset 7945 = 0x2c
assign /x dba 4, 811 offset 7918 = 0x2c
assign /x dba 4, 811 offset 7891 = 0x2c
assign /x dba 4, 811 offset 7864 = 0x2c
assign /x dba 4, 811 offset 7837 = 0x2c
assign /x dba 4, 811 offset 7810 = 0x2c
assign /x dba 4, 811 offset 7783 = 0x2c
assign /x dba 4, 811 offset 7756 = 0x2c
..

<======下面省略

 

10、把第九步運行的結果在bbed中運行

格式如下:

BBED> assign /x dba 4, 811 offset 8161 = 0x2c
ub1 rowdata[0]                              @8161     0x2c

BBED> assign /x dba 4, 811 offset 8134 = 0x2c
ub1 rowdata[0]                              @8134     0x2c

BBED> assign /x dba 4, 811 offset 8107 = 0x2c
ub1 rowdata[0]                              @8107     0x2c

BBED> assign /x dba 4, 811 offset 8080 = 0x2c
ub1 rowdata[0]                              @8080     0x2c

BBED> assign /x dba 4, 811 offset 8053 = 0x2c
ub1 rowdata[0]                              @8053     0x2c

BBED> assign /x dba 4, 811 offset 8026 = 0x2c
ub1 rowdata[0]                              @8026     0x2c

BBED> assign /x dba 4, 811 offset 7999 = 0x2c
ub1 rowdata[0]                              @7999     0x2c

BBED> assign /x dba 4, 811 offset 7972 = 0x2c
ub1 rowdata[0]                              @7972     0x2c

BBED> assign /x dba 4, 811 offset 7945 = 0x2c
ub1 rowdata[0]                              @7945     0x2c
 

<=====每個塊的行數修改完之後,會apply 該塊。

 

11、第十步運行完成之後,再次查詢表的內容

SQL> select count(*) from test;   <=====數據已完全恢復。

  COUNT(*)
----------
      9999

SQL>

 

BBED> x /rnc *kdbr[1]
rowdata[6677]                               @8134    
-------------
flag@8134: 0x2c (KDRHFL, KDRHFF, KDRHFH)  <====由原來的3c變成了2c
lock@8135: 0x00
cols@8136:    2

col    0[2] @8137: 2 
col   1[20] @8140: utjatydjtkuljbhjveqy


BBED> 

至此,TEST表的9999行數據全部找回,由於表被刪除了,表佔用的塊就可以被覆蓋。被覆蓋的塊的數據無法找回,此外上面的腳本只是針對表在一個數據文件上面,如果表涉及到多個數據文件,可以根據上面的腳本進行改寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章