zoukankan      html  css  js  c++  java
  • First Impression on BBED: recover deleted rows

    Row Flag Structure

    在看一个数据块的dump文件的时候,经常会发现类似如下的信息...

    tl: 12 fb: --H-FL-- lb: 0x1 cc: 2


    其中fb, lb, cc就是每一行数据头的信息,分别表示Row Flag, Lock Byte (ITL entry), Column Count. (tl, 应该表示每一行数据实际占用的空间大小,包括row header, 每一个column实际占用的字节数,和用来存储每个column长度的overhead。 tl的信息并没有实际存储。)

    那么ROW Flag中的8个bit分别表示什么意思呢 (例如这里的H, F, L)?

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

    这8个bit从高到低依次是:

    (128) : Cluster Key

    (64) : Cluster Table Member

    (32) : Header of row piece

    (16): Deleted

    (8) : First data piece

    (4) : Last data piece

    (2) : First column continues from previous piece

    (1) : Last column continues in next piece

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

    因此,如果表中的一行记录完全处于一个block中(没有出现row chain, row migration), 不是属于聚簇表,也没有被删除,那么这一行数据的flag应该就是

    32 (Header of row piece) + 8 (First data piece) + 4 (Last data piece) = 44 (0x2c), 这个也就是在dump文件中看到的标识--H-FL--

    Recover Deleted Rows

    那么恢复删除的数据跟上面提到的Row Flag有什么关系呢?注意到Row Flag中有一位是用来标示当前的行有没有被删除(Deleted),正常情况下这个bit是没有被set的,一旦当前行被删除了,这个bit就会被set了,而该行的数据并没有实际从block中擦除掉。因此一种很自然的想法就是,能不能通过简单地修改这个标识位,来恢复删除的数据呢? 答案自然是肯定的。
    首先建立一个测试表,如下...
    SQL> select * from test;

    ID NAME
    ---------- ----------
    1 Frank
    2 Fraud

    SQL
    > alter system dump datafile 4 block 388;
    查看dump文件可以看到这两条记录...
    block_row_dump:
    tab
    0, row 0, @0x1f8c
    tl:
    12 fb: --H-FL-- lb: 0x1 cc: 2
    col 0: [ 2] c1 02
    col
    1: [ 5] 46 72 61 6e 6b
    tab
    0, row 1, @0x1f80
    tl:
    12 fb: --H-FL-- lb: 0x1 cc: 2
    col 0: [ 2] c1 03
    col
    1: [ 5] 46 72 61 75 64
    如果现在删除第二行数据,再看看dump文件内容有什么变化...
    SQL> delete from test where id = 2;

    1 row deleted.

    SQL
    > commit;

    Commit complete.

    SQL
    > alter system dump datafile 4 block 388;

    System altered.
    查看dump文件...
    block_row_dump:
    tab
    0, row 0, @0x1f8c
    tl:
    12 fb: --H-FL-- lb: 0x0 cc: 2
    col 0: [ 2] c1 02
    col
    1: [ 5] 46 72 61 6e 6b
    tab
    0, row 1, @0x1f80
    tl:
    2 fb: --HDFL-- lb: 0x2
    end_of_block_dump
    注意表中的第二行数据的标志位图信息由--H-FL--变成了--HDFL-- 第四个标志位被置成了D(deleted), 表示第二行数据被删除了。
    数据被删除了,只是相应地更新了那一行的标志位,数据在block上还是存在的,可以通过bbed的输出来验证这一点...
    BBED> set dba 4, 388
    DBA
    0x01000184 (16777604 4,388)

    BBED
    > p kdbr
    sb2 kdbr[
    0] @118 8076
    sb2 kdbr[
    1] @120 8064

    BBED
    > p *kdbr[1]
    rowdata[
    0]
    ----------
    ub1 rowdata[
    0] @8164 0x3c

    BBED
    > x /rnc
    rowdata[
    0] @8164
    ----------
    flag
    @8164: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
    lock
    @8165: 0x02
    cols
    @8166: 0



    BBED
    > dump /v dba 4, 388 offset 8164
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    388 Offsets: 8164 to 8191 Dba:0x01000184
    -------------------------------------------------------
    3c020202 c1030546
    72617564 2c000202 l <...�..Fraud,...
    c1020546 72616e6b 01069bdb l �..Frank...

    <
    16 bytes per line>

    BBED
    >
    从上面的输出可以看到第二行的标志位(值变成了0x3c)多了一个KDRHFD,表示这一行被删除了,但是从dump命令的输出可以看出数据(Fraud)还是存在的。只要这部分的数据没有被覆盖掉,应该可以通过修改数据行的标志位信息,把数据恢复回来的。
    那么怎么去修改这个标志位呢,其实想想应该也不困难,只要找到标志位的offset, 通过modify命令将值从0x3c改回成0x2c就可以了。
    从上面的examine命令的输出结果,可以得到第二行数据的标志位的offset为8164,那么改变这个值就不是难事了...
    BBED> modify /x 2c offset 8164
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    388 Offsets: 8164 to 8191 Dba:0x01000184
    ------------------------------------------------------------------------
    2c020202 c1030546
    72617564 2c000202 c1020546 72616e6b 01069bdb

    <
    32 bytes per line>

    BBED
    > dump /v dba 4, 388 offset 8164
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    388 Offsets: 8164 to 8191 Dba:0x01000184
    -------------------------------------------------------
    2c020202 c1030546
    72617564 2c000202 l ,...�..Fraud,...
    c1020546 72616e6b 01069bdb l �..Frank...

    <
    16 bytes per line>

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

    BBED
    > x /r
    rowdata[
    0] @8164
    ----------
    flag
    @8164: 0x2c (KDRHFL, KDRHFF, KDRHFH)
    lock
    @8165: 0x02
    cols
    @8166: 2

    col
    0[2] @8167: 0xc1 0x03
    col
    1[5] @8170: 0x46 0x72 0x61 0x75 0x64


    BBED
    > x /rnc
    rowdata[
    0] @8164
    ----------
    flag
    @8164: 0x2c (KDRHFL, KDRHFF, KDRHFH)
    lock
    @8165: 0x02
    cols
    @8166: 2

    col
    0[2] @8167: 2
    col
    1[5] @8170: Fraud
    从上面的输出可以看出,这条数据已经被“恢复”回来了。那么剩下要做的事情就是更新block的checksum, 
    BBED> sum dba 4, 388 apply
    Check value
    for File 4, Block 388:
    current
    = 0x4fb9, required = 0x4fb9
    现在通过SQL访问表TEST看看数据有没有被“恢复”回来...
    SQL> alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Frank
    2 Fraud

    SQL
    >
    很显然,第二行数据被“恢复”回来了。
  • 相关阅读:
    一个喜欢研究车的80后开车人,自己的经验和感受
    35岁前务必成功的12级跳(男女通用) 转
    如何注册ocx文件
    plsql连接oracle数据库
    float过后 高度无法自适应的解决方法
    Mysql 中文中繁杂的字 插入报错的 解决方案
    power designer 教程
    表单文本框输入时提示文字消失
    diskpart分盘代码
    linux svn 中文 https://my.oschina.net/VASKS/blog/659236
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/1958592.html
Copyright © 2011-2022 走看看