恢复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 的数据已经恢复出来。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章