zoukankan      html  css  js  c++  java
  • First Impression on BBED: modify table data

    BBED功能相当强大,因为可以用来修改block上的内容,因此很显然可以通过BBED来修改表上的数据,直接绕过通过SQL语句对表的操作。

    本文尝试通过BBED来修改表中的一条记录。

    建立实验环境

    首先建立实验环境,建立一张表test, 插入一条记录 (1, 'Frank'), 如下...

    SQL> create user frank identified by frank;

    User created.

    SQL
    > grant resource, connect to frank;

    Grant succeeded.

    SQL
    > conn frank/frank
    Connected.
    SQL
    > create table test(id integer, name varchar2(10));

    Table created.

    SQL
    > insert into test values(1, 'Frank');

    1 row created.

    SQL
    > commit;

    Commit complete.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Frank

    SQL
    > select rowid, dbms_rowid.rowid_block_number(rowid), dbms_rowid.rowid_relative_fno(rowid)
    2 from test;

    ROWID DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
    ------------------ ------------------------------------
    DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)
    ------------------------------------
    AAAM8RAAEAAAAGUAAA 404
    4


    SQL
    > alter system dump file 4 block 404;
    alter system dump file 4 block 404
    *
    ERROR at line
    1:
    ORA
    -01961: Invalid dump option


    SQL
    > alter system dump datafile 4 block 404;
    alter system dump datafile 4 block 404
    *
    ERROR at line
    1:
    ORA
    -01031: insufficient privileges


    SQL
    > conn / as sysdba
    Connected.
    SQL
    > grant alter system to frank;

    Grant succeeded.

    SQL
    > conn frank/frank
    Connected.
    SQL
    > alter system dump datafile 4 block 404;

    System altered.


    通过上面的操作,确定了我们刚才在表test中插入的一条记录位于4号数据文件上第404个block上面。

     

    设置BBED

    现在把BBED 的dba 设置成 4, 404

    [oracle@ora10g ~]$ bbed
    Password:

    BBED: Release
    2.0.0.0.0 - Limited Production on Thu Feb 17 20:33:45 2011

    Copyright (c)
    1982, 2005, Oracle. All rights reserved.

    ************* !!! For Oracle Internal Use only !!! ***************

    BBED
    > set dba 4, 404
    BBED
    -00312: no LISTFILE specified


    BBED
    > set listfile='/u01/app/oracle/temp/listdatafile.log'
    BBED
    -00202: invalid parameter (=)


    BBED
    > set listfile '/u01/app/oracle/temp/listdatafile.log'
    LISTFILE
    /u01/app/oracle/temp/listdatafile.log

    BBED
    > set dba 4, 404
    DBA
    0x01000194 (16777620 4,404)

    可以通过BBED来查看我们刚才在表TEST中插入的记录,如下,(kbdr中这个数组大小为1,表示只有一条记录)

    BBED> p kdbr
    sb2 kdbr[
    0] @118 8076

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

    BBED> x /r
    rowdata[
    0] @8176
    ----------
    flag
    @8176: 0x2c (KDRHFL, KDRHFF, KDRHFH)
    lock
    @8177: 0x01
    cols
    @8178: 2

    col
    0[2] @8179: 0xc1 0x02
    col
    1[5] @8182: 0x46 0x72 0x61 0x6e 0x6b


    BBED
    > x /rnc
    rowdata[
    0] @8176
    ----------
    flag
    @8176: 0x2c (KDRHFL, KDRHFF, KDRHFH)
    lock
    @8177: 0x01
    cols
    @8178: 2

    col
    0[2] @8179: 1
    col
    1[5] @8182: Frank

    注意这里面用到的e(x)amine命令, 参数/r表示显示oracle表中每一行记录, /nc表示第一列为数字类型(1),第二列为字符串类型('Frank')。 从上面的输出可以看出,表中有一行记录(1, 'Frank').  同时注意到每一行的开始有3个字节的overhead, 分别表示flag, lock, column count, 因此虽然表中第一行数据从offset 8176开始,实际的数据是从offset 8179开始。而且每个column的数据前面是有至少一个字节是用来存储改column占用的字节数,所以虽然'Frank'这个column是从offset 8182开始,实际存储的字符串'Frank'是从offset 8183开始的。

     

    修改数据

    现在尝试把表中的'Frank'改成'Fraud'.

    首先需要确定'Frank'这个字符串在block中的位置(offset) , 通过find命令来找到大概的位置,然后通过dump命令来进一步确认 (其实从上面的examine命令输出已经可以判断出来Frank这个字符串是从offset 8183开始的),

    BBED> find /c Frank
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8183 to 8191 Dba:0x01000194
    ------------------------------------------------------------------------
    4672616e 6b030645 1e

    <
    32 bytes per line>

    BBED
    > dump /v dba 4, 404 offset 8183 count 64
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8183 to 8191 Dba:0x01000194
    -------------------------------------------------------
    4672616e 6b030645 1e l Frank..E.

    <
    16 bytes per line>

    可以确定下来Frank是从offset 8183开始的。那么下面可以通过modify命令来进行数据的修改,将'Frank'修改为'Fraud'...

    BBED> modify /c Fraud dba 4, 404 offset 8183
    BBED
    -00215: editing not allowed in BROWSE mode


    BBED
    > set mode edit
    MODE Edit

    BBED
    > modify /c Fraud dba 4, 404 offset 8183
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8183 to 8191 Dba:0x01000194
    ------------------------------------------------------------------------
    46726175 64030645 1e

    <
    32 bytes per line>

    BBED
    > dump /v dba 4, 404 offset 8183
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8183 to 8191 Dba:0x01000194
    -------------------------------------------------------
    46726175 64030645 1e l Fraud..E.

    <
    16 bytes per line>

    通过dump命令可以看出block的内容却是被修改成了Fraud了。那么现在通过sql*plus来查看数据是不是改变了...

    SQL> select * from test;

    ID NAME
    ---------- ----------
    1 Frank

    SQL
    > alter system flush buffer cache;
    alter system flush buffer cache
    *
    ERROR at line
    1:
    ORA
    -02000: missing SHARED_POOL/BUFFER_CACHE/GLOBAL CONTEXT keyword


    SQL
    > alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;
    select * from test
    *
    ERROR at line
    1:
    ORA
    -01578: ORACLE data block corrupted (file # 4, block # 404)
    ORA
    -01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'

    在查询表之前,通过alter system flush buffer_cache来清空内存中的数据缓存,第一次得到的数据有可能是内存中的。flush之后再重新查询,发现报了一个错误,说block被破坏了!这是因为通过BBED修改了之后没有进行block checksum的重新计算,造成block表现为corrupted.

    可以通过sum命令来更新block的checksum,

    BBED> sum dba 4, 404
    Check value
    for File 4, Block 404:
    current
    = 0x61de, required = 0x6ec5

    BBED
    > sum dba 4, 404 apply
    Check value
    for File 4, Block 404:
    current
    = 0x6ec5, required = 0x6ec5

    现在再通过sql*plus来查看一下,

    SQL> select * from test;
    select * from test
    *
    ERROR at line
    1:
    ORA
    -01578: ORACLE data block corrupted (file # 4, block # 404)
    ORA
    -01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'


    SQL
    > alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Fraud

    现在看到表TEST的内容被改成了Fraud. 需要注意的是,访问表之前,还需要执行下alter system flush buffer_cache命令。

    数据块的恢复(revert)

    可以通过revert命令来撤销刚才对数据库块的修改,使之回退到BBED启动时候的那个状态。注意,用UNDO命令会失败,因为已经进行过了block的checksum重计算了。操作如下,

    BBED> undo
    BBED
    > modify /x 4672616E6B filename '/u01/app/oracle/oradata/orcl/users01.dbf' block 404. offset 8183.
    BBED
    -00209: invalid number (4672616E6B)



    BBED
    > revert dba 4, 404
    All changes made to this block will be rolled back. Proceed
    ? (Y/N) Y
    Reverted file '
    /u01/app/oracle/oradata/orcl/users01.dbf', block 404

    现在通过sql*plus查询确认下...

    SQL> alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Frank

    可以看到Name又从'Fraud'变成了'Frank'了。

    再来一次

    现在尝试往表TEST再插入一条记录(2, 'HelloFrank'),

    SQL> insert into test values(2, 'HelloFrank');

    1 row created.

    SQL
    > commit;

    Commit complete.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Frank
    2 HelloFrank

    SQL
    > alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    1 Frank
    2 HelloFrank

    现在再通过print命令来查看kdbr,发现现在有两条记录了,而且第一条记录的offset还是8176,这个是显然的,因为数据是从block尾部往上插入的,第一条数据位于block的底部,offset并不会因为新数据的插入而改变。

    BBED> set dba 4, 404
    DBA
    0x01000194 (16777620 4,404)

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

    BBED
    > p kdbr[0]
    sb2 kdbr[
    0] @118 8076

    BBED
    > p *kdbr[0]
    rowdata[
    17]
    -----------
    ub1 rowdata[
    17] @8176 0x2c

    BBED
    > p /c offset 8176
    rowdata[
    17]
    -----------
    ub1 rowdata[
    17] @8176 ,

    BBED
    > dump /v dba 4, 404 offset 8176
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8176 to 8191 Dba:0x01000194
    -------------------------------------------------------
    2c010202 c1020546 72616e6b 0206ec28 l ,...�..Frank..

    <
    16 bytes per line>

    BBED
    >

    新插入的第二条记录是从offset 8159开始的...

    BBED> dump /v dba 4, 404 offset 8159
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8159 to 8191 Dba:0x01000194
    -------------------------------------------------------
    2c020202 c1030a48 656c6c6f 4672616e l ,...�..HelloFran
    6b2c0102 02c10205 4672616e 6b0206ec l k,...�..Frank..
    28 l (

    <
    16 bytes per line>

    BBED
    > dump /v dba 4, 404 offset 8166
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8166 to 8191 Dba:0x01000194
    -------------------------------------------------------
    48656c6c 6f467261 6e6b2c01 0202c102 l HelloFrank,...�.
    05467261 6e6b0206 ec28 l .Frank..

    <
    16 bytes per line>

    BBED
    >

    现在尝试把'HelloFrank'改成'Fraud'试一下...

    BBED> modify /c Fraud dba 4, 404 offset 8166
    BBED
    -00215: editing not allowed in BROWSE mode


    BBED
    > set mode edit
    MODE Edit

    BBED
    > modify /c Fraud dba 4, 404 offset 8166
    Warning: contents of previous BIFILE will be lost. Proceed
    ? (Y/N) Y
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8166 to 8191 Dba:0x01000194
    ------------------------------------------------------------------------
    46726175 64467261 6e6b2c01 0202c102 05467261 6e6b0206 ec28

    <
    32 bytes per line>

    BBED
    > dump /v dba 4, 404 offset 8166
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8166 to 8191 Dba:0x01000194
    -------------------------------------------------------
    46726175 64467261 6e6b2c01 0202c102 l FraudFrank,...�.
    05467261 6e6b0206 ec28 l .Frank..

    <
    16 bytes per line>

    可以看到'Fraud'不会把'HelloFrank'都替换掉,只是'Fraud'这5个字符覆盖了'Hello'这5个字符。

    那如果用'I am Frank!'这个字符串替换'HelloFrank'呢? (注意到需要用引号把I am Frank!给括起来)

    BBED> modify /c I am Frank! dba 4, 404 offset 8166
    BBED
    -00207: invalid offset specifier (am)


    BBED
    > modify /c "I am Frank!" dba 4, 404 offset 8166
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8166 to 8191 Dba:0x01000194
    ------------------------------------------------------------------------
    4920616d
    20467261 6e6b2101 0202c102 05467261 6e6b0206 ec28

    <
    32 bytes per line>

    BBED
    > dump /v dba 4, 404 offset 8166
    File:
    /u01/app/oracle/oradata/orcl/users01.dbf (4)
    Block:
    404 Offsets: 8166 to 8191 Dba:0x01000194
    -------------------------------------------------------
    4920616d
    20467261 6e6b2101 0202c102 l I am Frank!...�.
    05467261 6e6b0206 ec28 l .Frank..

    <
    16 bytes per line>

    BBED
    >

    从dump结果来看,数据块被修改了,那么用SQL来访问表的结果是什么呢?

    SQL> alter system flush buffer_cache;

    System altered.

    SQL
    > select * from test;

    ID NAME
    ---------- ----------
    2 I am Frank

    这个结果很奇怪,第一行数据(1, ’Frank')丢失了! 而且注意Name为(I am Frank), 少了一个感叹号(!).

    因为Name这一列的数据类型是varchar2(10), 最大是10个字符,而我通过BBED写入了11个字符,把下一行数据(也就是表中的第一行数据(1, 'Frank'))的开始部分的标志位的信息给覆盖掉了!!因此SQL语句不能正确读出第一行数据了,造成了数据的丢失!!

    从这个案例也可以看出用BBED一定要小心再小心, 很容易就可以把一个block给破坏了!

  • 相关阅读:
    什么是 bean 的自动装配?
    什么是 Spring 的内部 bean?
    什么是 Spring 的 MVC 框架?
    Spring AOP and AspectJ AOP 有什么区别?
    解释 JDBC 抽象和 DAO 模块?
    volatile 类型变量提供什么保证?
    一个 Spring Bean 定义 包含什么?
    什么是 Spring MVC 框架的控制器?
    使用 Spring 访问 Hibernate 的方法有哪些?
    什么是 Callable 和 Future?
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/1957342.html
Copyright © 2011-2022 走看看