恢復delete 的rows

恢復delete 的rows

       Whenrows are deleted in Oracle the data is not actually removed. The row is simplymarked as deleted and the free space counters and pointers adjustedaccordingly. The status of a row is stored in the Row Header which occupies thefirst few bytes of each row.

       當row 被delete 的時候,實際上data 並沒有被remove,只是將該row 標記爲delete,然後其對應的空間被統計爲free space。 row 的status 存在每個row的row header裏。

 

       TheRow Header consists of the Row Flag, Lock Byte (ITL entry) and Column Count.The first of these - the Row Flag - is a single byte that holds a bitmask thatshows the status of the row. The bitmask is decoded as follows:

      image  

 

我們dump 一個block,看一個row Flag,來幫助理解這個bitmask。
 

SYS@dave2(db2)> alter system dump datafile1 block 115362;

System altered.

SYS@dave2(db2)> oradebug setmypid

Statement processed.

SYS@dave2(db2)> oradebug tracefile_name

/u01/app/oracle/admin/dave2/udump/dave2_ora_9396.trc

 

trace file有關row的信息如下:

block_row_dump:

tab 0, row 0, @0x1f90

tl: 16 fb: --H-FL--lb: 0x1  cc: 1             --在這裏fb代表Row Flag,lb代表Lock Byte ,cc代表column Count. 
                                              --此時Row Flag = 32+8+4=44 即16進制的2c.

col 0: [12]  44 4d 4d 20 20 69 73 2044 42 41 21

tab 0, row 1, @0x1f7b

tl: 21 fb: --H-FL-- lb: 0x2  cc: 1

col 0: [17]  64 6d 6d 65 20 6c 69 6b65 20 4f 72 61 63 6c 65 21

end_of_block_dump

 

我們的表dvd裏只有2行記錄,所以這裏顯示的row 爲2.

注意這裏的fb: --H-FL--。 其有8個選項,每個值分別與bitmask 對應。

 

 

       Therefore,columns that fit within a single block, are not chained, migrated or part of aclustered table and are not deleted will have the following attributes:

       (1)Head of Row Piece

       (2)First Data Piece

       (3)Last Data Piece

       如果一個row 沒有被刪除,那麼它就具有上面的3個屬性,即Flag 表示爲:--H-FL--. 這裏的字母分別代表屬性的首字母。其對應的值:32 + 8 + 4 =44 or 0x2c.

       如果一個row 被delete了,那麼row flag 就會更新,bitmask 裏的deleted 被設置爲16. 此時row flag 爲: 32 + 16 + 8 + 4 = 60 or 0x3c.

 

驗證一下:

SYS@dave2(db2)> delete from dvd whererownum=1;

1 row deleted.

SYS@dave2(db2)> commit;

Commit complete.

 

查看dump 的標記:

block_row_dump:

tab 0, row 0, @0x1f90

tl: 2 fb: --HDFL--lb: 0x1

tab 0, row 1, @0x1f7b

tl: 21 fb: --H-FL-- lb: 0x0  cc: 1

col 0: [17]  64 6d 6d 65 20 6c 69 6b65 20 4f 72 61 63 6c 65 21

end_of_block_dump

 

這裏的row 1flag 變成了--HDFL--。

 

現在我們用bbed 將刪除的row 1 內容找回來。

 

BBED> set dba1,115362 offset 0

       DBA             0x0041c2a2(4309666 1,115362)

       OFFSET          0

 

BBED> find /c DMM

 File: /u01/app/oracle/oradata/dave2/system01.dbf(1)

 Block: 115362           Offsets: 8176 to 8191           Dba:0x0041c2a2

------------------------------------------------------------------------

 444d4d20 20697320 44424121 020616b3

 

 <32 bytes per line>

 

BBED> d /v dba 1,115362 offset 8176 count 128

 File:/u01/app/oracle/oradata/dave2/system01.dbf (1)

 Block: 115362 Offsets: 8176 to 8191 Dba:0x0041c2a2

-------------------------------------------------------

 444d4d20 20697320 44424121 020616b3 l DMM  is DBA!...3

 

 <16 bytes per line>

 

注意:我們還是可以通過dump查看我們delete 掉的row記錄。但是在sql裏用select 已經看出到了。 這個也證明,delete 並未真正的刪除data。

我們的row 的內容保存在offset 8176的位置,我們將offset 往前移動一段,再dump,來確定row header的內容。 

這個移位有一定的規律。 我們看一下:

BBED> d /v dba 1,115362 offset 8176 count 128

 File: /u01/app/oracle/oradata/dave2/system01.dbf(1)

 Block: 115362 Offsets: 8176 to 8191 Dba:0x0041c2a2

-------------------------------------------------------

 444d4d20 20697320 44424121 020616b3 l DMM  is DBA!...3

 

我們的一條記錄是從444d4d20開始的,此時的offsets8176開始的。我們offset 減小一位,在dump:

 

BBED> d /v dba 1,115362 offset 8175

 File:/u01/app/oracle/oradata/dave2/system01.dbf (1)

 Block: 115362 Offsets: 8175 to 8191 Dba:0x0041c2a2

-------------------------------------------------------

 0c444d4d 20206973 20444241 210206d7 l.DMM  is DBA!..×

 73                                  l s

 <16 bytes per line>

 此時dump 的內容多了2個字符,而一個完整的是8個字符,所以要想完整的顯示,一次要減少4個offsets。

BBED> d /v dba 1,115362 offset 8172

 File:/u01/app/oracle/oradata/dave2/system01.dbf (1)

 Block: 115362 Offsets: 8172 to 8191 Dba:0x0041c2a2

-------------------------------------------------------

 3c01010c 444d4d20 20697320 44424121 l <...DMM  is DBA!

 0206d773                            l ..×s

 

 <16 bytes per line>

 這裏已經出現了我們3c(deleted)標誌,但是注意這裏的位置的根據我們的查找的字符串來分的,實際在block裏的分割方式不一樣按照我們的offset 來進行。 
我們可以通過row directory 來進行一個確認。

 
我們print row directory 確認一下:

BBED> p kdbr

sb2 kdbr[0]                                 @110      8080

sb2 kdbr[1]                                 @112      8059

 

BBED> p *kdbr[0]

rowdata[21]

-----------

ub1 rowdata[21]                             @8172     0x3c

 

BBED> p *kdbr[1]

rowdata[0]

----------

ub1 rowdata[0]                              @8151     0x2c

 

通過row directory,我們可以確認對應row記錄的row header保存在offset 8172的位置,值爲3c。 我們find 字符串的目的就是爲了和row directory 中的offset 進行比較。
他們相近時,就可以確定。

現在我們將@8172位置的3c 變成2c。 即從deleted 變成正常。

 

BBED> modify /x 2c offset 8172

 File:/u01/app/oracle/oradata/dave2/system01.dbf (1)

 Block: 115362           Offsets: 8172 to 8191           Dba:0x0041c2a2

------------------------------------------------------------------------

 2c01010c 444d4d20 20697320 44424121 0206d773

 

 <32 bytes per line>

 

BBED> sum apply

Check value for File 1, Block 115362:

current = 0x2cb4, required = 0x2cb4

 

--flush buffer cache,然後查詢

SYS@dave2(db2)> alter system flushbuffer_cache;

System altered.

 

SYS@dave2(db2)> select * from dvd;

JOB

--------------------------------------------------------------------------------

DMM is DBA!

Dave like Oracle!

之前delete 的數據已經恢復出來。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章