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给破坏了!

  • 相关阅读:
    RVM Ruby 版本管理器的删除 Gatling
    JWT 构建Rails API 授权登录
    Linux grep根据关键字匹配前后几行
    bootstrap-table 常用总结-树形结构
    linux 下jq的使用
    SHELL脚本获取域名对应的IP地址
    golang将切片或数组进行分组
    linux的统计实现
    Linux:“awk”命令的妙用
    rails 上传文件
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/1957342.html
Copyright © 2011-2022 走看看