是用bbed工具模擬對塊的破壞,並使用rman bock recover進行塊恢復

蘭在晨發表於2012-09-04

第一部分 .       概述

一、        實驗環境

執行環境:

[root@localhost ~]# lsb_release -a

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch

Distributor ID: RedHatEnterpriseServer

Description:    Red Hat Enterprise Linux Server release 5.4 (Tikanga)

Release:        5.4

Codename:       Tikanga

資料庫版本:

SQL> select * from v$version;

 

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE    10.2.0.1.0      Production

TNS for Linux: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 - Production

 

二、        實驗目標

使用bbed工具對hr使用者下的departments表所在的一個塊進行破壞,然後使用RMAN block recover進行塊恢復。

第二部分 .       技術概述

一、        實驗步驟

1.       Linking bbed

在使用bbed工具前必須先linkbbed的程式碼會和oracle的資料庫一起裝載在unix或者linux上,但是並沒有被linked

a)        編譯bbed

[oracle@lzc lib]$ make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed

Linking BBED utility (bbed)

rm -f /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/bbed

gcc -o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/bbed -L/u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/ -L/u01/app/oracle/product/10.2.0.1/db_1/lib/ -L/u01/app/oracle/product/10.2.0.1/db_1/lib/stubs/ -L/usr/lib -lirc  /u01/app/oracle/product/10.2.0.1/db_1/lib/s0main.o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/ssbbded.o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/sbbdpt.o `cat /u-ldl

。。。(省略部分)

 -lm   -L/u01/app/oracle/product/10.2.0.1/db_1/lib

檢視一下是否成功編譯

[oracle@lzc lib]$ ll bbed

-rwxr-xr-x 1 oracle oinstall 536161 Aug 31 09:50 bbed

可以看到成功編譯!

b)        設定環境變數

為了使用方便,在任何目錄下都能夠隨意呼叫bbed的命令,我們可以把bbed所在的目錄/u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib新增到path環境變數下,或者做一個軟連線。

這裡我選擇第一種。

至於如何新增修改PATH環境變數,就不用多說了。在/home/oracle目錄下修改.bash_profile檔案即可。

2.       Starting bbed

a)        建立listfile檔案filelinux.log

SQL> select file#||' '||name||' '||bytes from v$datafile;

FILE#||''||NAME||''||BYTES

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

1 /u01/app/oracle/oradata/dblzc/system01.dbf 513802240

2 /u01/app/oracle/oradata/dblzc/undotbs01.dbf 83886080

3 /u01/app/oracle/oradata/dblzc/sysaux01.dbf 293601280

4 /u01/app/oracle/oradata/dblzc/users01.dbf 15728640

5 /u01/app/oracle/oradata/dblzc/soe.dbf 3436183552

b)        建立parfile檔案bbed.par

blocksize=8192           //該引數為資料庫的default block size

listfile=/home/oracle/bbed_test/filelinux.log  //上面建立的listfile檔案

mode=edit    //進入bbed的模式,有browseedit兩個引數。在browse模式下只能瀏覽,不能進行修改。

c)         檢視要修改的資料庫塊的資訊

  1* select file_id,owner,segment_name,block_id from dba_extents where segment_name='DEPARTMENTS' and WNER='HR'

   FILE_ID OWNER SEGMENT_NAME           BLOCK_ID

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

         4 HR    DEPARTMENTS                 121

這裡的的block_id指的是這個塊所在區的第一個塊的block_id

d)        檢視錶中記錄的資訊

SQL> select * from departments;

DEPARTMENT_ID DEPARTMENT_NAME                MANAGER_ID LOCATION_ID

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

           10 Administration                        200        1700

           20 Marketing                             201        1800

           50 Shipping                              124        1500

           60 IT                                    103        1400

           80 Sales                                 149        2500

           90 Executive                             100        1700

          110 Accounting                            205        1700

          190  contracting                                     1700

8 rows selected.

e)        檢視每行記錄對應儲存的塊號

SQL> select dbms_rowid.rowid_block_number(rowid) from departments;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

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

                                 127

                                 127

                                 127

                                 127

                                 127

                                 127

                                 127

                                 127

8 rows selected.

這裡可以看到表中每行資料所在的block_id。由於測試資料比較少,所以departments這個表中的所有資料都在127這個資料塊中。

從以上的查詢我們可以獲得我們所要操作的塊的相關資訊。假設我們現在修改department表所在的塊的資訊。File_id=4 block_id=127

3.       進入bbed

[oracle@lzc bbed_test]$ bbed parfile=bbed.par

Password:

BBED: Release 2.0.0.0.0 - Limited Production on Fri Aug 31 11:42:16 2012

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

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

BBED>

BBED的密碼是blockedit,這個密碼在任何客戶端上都是一樣的。如果你對這個工具的oracle內部安全程式碼足夠了解,也可以使用standard reverse-engineering技術進行修改。

可以通過下面兩個命令來檢視,剛在在引數檔案中設定的引數

BBED> show

        FILE#           4

        BLOCK#          127

        OFFSET          7554

        DBA             0x0100007f (16777343 4,127)

        FILENAME        /u01/app/oracle/oradata/dblzc/users01.dbf

        BIFILE          bifile.bbd

        LISTFILE        /home/oracle/bbed_test/filelinux.log

        BLOCKSIZE       8192

        MODE            Edit

        EDIT            Unrecoverable

        IBASE           Dec

        OBASE           Dec

        WIDTH           80

        COUNT           512

        LOGFILE         log.bbd

        SPOOL           No

 

BBED> info

 File#  Name                                                        Size(blks)

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

     1  /u01/app/oracle/oradata/dblzc/system01.dbf                       62720

     2  /u01/app/oracle/oradata/dblzc/undotbs01.dbf                      10240

     3  /u01/app/oracle/oradata/dblzc/sysaux01.dbf                       35840

     4  /u01/app/oracle/oradata/dblzc/users01.dbf                         1920

     5  /u01/app/oracle/oradata/dblzc/soe.dbf                           419456

4.       修改塊中的資料

a)        設定當前資料塊

BBED> set dba 4,127

        DBA             0x0100007f (16777343 4,127)

引數dba為資料塊的地址data block address

假設現在我要修改departments表中包含’Sale’字元的那一行

BBED> find /c Sale

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 127              Offsets: 7554 to 8065           Dba:0x0100007f

<32 bytes per line>

通過find命令我們可以找到改行在127塊中的offsets

b)        檢視塊中的內容

然後我們可以通過改行所在的offset檢視對應儲存在塊中的資料

BBED> dump /v dba 4,127 offset 7554 count 5

File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 127     Offsets: 7554 to 8065  Dba:0x0100007f

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

 53616c65 7303c202 3202c21a 2c020402 l Sales..2..,...

 Dump命令使用來顯示指定的塊的內容,通過offset可以更進一步檢視到每一行中的內容。

通過count引數控制向螢幕輸出的位元組數。要根據你所要查詢的字元的長度來設定。

c)         修改塊中的內容

BBED> modify /c lanzaichen dba 4,127 offset 7554

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 127              Offsets: 7554 to 8065           Dba:0x0100007f

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

 6c616e7a 61696368 656ec21a 2c020402 c13d0249 5403c202 0402c20f 2c020402

 c1330853 68697070 696e6703 c2021902 c2102c02 0402c115 094d6172 6b657469

 6e6703c2 030202c2 132c0204 02c10b0e 41646d69 6e697374 72617469 6f6e02c2

 0302c212 3c020403 c2025b0c 20636f6e 74726163 74696e67 ff02c212 3c020403

 c2020b0a 4163636f 756e7469 6e6703c2 030602c2 123c0204 02c15b09 45786563

部分省略。。。

再次重新檢視一下塊中的內容

BBED> dump /v dba 4,127 offset 7554 count 10 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 127     Offsets: 7554 to 8065  Dba:0x0100007f

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

 6c616e7a 61696368 656ec21a 2c020402 l lanzaichen

可以看到第一行中的資料已經被修改掉,如果此時我們不對剛才的操作執行sum命令apply修改的話。由於校驗值發生了變化,在資料庫中這個資料塊就會報錯。

然後回到資料庫中重新檢視錶中的資料,看是否能夠正常檢索。

5.       診斷壞塊

前面我們已經成功的修改了departments表所在的塊的內容,由於沒有使用sum命令apply設定。所以,被修改的塊不能被正常檢索。那我們如何找到這個壞塊呢?

a)        通過檢索資料

在檢索資料時會對資料所在的資料檔案進行掃描(被檢索的資料不在記憶體中),可以檢測到資料檔案中的壞塊。

SQL> conn / as sysdba

Connected.

SQL> alter system flush buffer_cache;

System altered.

從表中檢索內容之前要先把資料庫高速緩衝區(data buffer cache)中的資料清除。

SQL> conn hr/oracle

Connected.

SQL> select * from departments;

select * from departments

             *

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 4, block # 127)

ORA-01110: data file 4: '/u01/app/oracle/oradata/dblzc/users01.dbf'

可以看到,我們剛才修改的資料被報錯。

b)        Dbverify工具

SQL> select block_size  from v$datafile where file#=4;

BLOCK_SIZE

----------

      8192

SQL> host

 [oracle@lzc ~]$ dbv file=/u01/app/oracle/oradata/dblzc/users01.dbf blocksize=8192

DBVERIFY: Release 10.2.0.1.0 - Production on Fri Aug 31 15:29:13 2012

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

DBVERIFY - Verification starting : FILE = /u01/app/oracle/oradata/dblzc/users01.dbf

Page 121 is marked corrupt

Corrupt block relative dba: 0x01000079 (file 4, block 121)

Bad header found during dbv:

Data in bad block:

 type: 67 format: 7 rdba: 0x0a545055

 last change scn: 0x0000.00149f2b seq: 0x2 flg: 0x04

 spare1: 0x52 spare2: 0x52 spare3: 0x0

 consistency value in tail: 0x9f2b2002

 check value in block header: 0xd12

 computed block checksum: 0xe449

Page 122 is marked corrupt

Corrupt block relative dba: 0x0100007a (file 4, block 122)

Bad header found during dbv:

Data in bad block:

 type: 67 format: 7 rdba: 0x0a545055

 last change scn: 0x0000.00149e97 seq: 0x2 flg: 0x04

 spare1: 0x52 spare2: 0x52 spare3: 0x0

 consistency value in tail: 0x9e972102

 check value in block header: 0x4dd4

 computed block checksum: 0xe44b

Page 127 is marked corrupt

Corrupt block relative dba: 0x0100007f (file 4, block 127)

Bad check value found during dbv:

Data in bad block:

 type: 6 format: 2 rdba: 0x0100007f

 last change scn: 0x0000.00149fa2 seq: 0x1 flg: 0x06

 spare1: 0x0 spare2: 0x0 spare3: 0x0

 consistency value in tail: 0x9fa20601

 check value in block header: 0xae4a

 computed block checksum: 0x73d9

DBVERIFY - Verification complete

Total Pages Examined         : 1920

Total Pages Processed (Data) : 347

Total Pages Failing   (Data) : 0

Total Pages Processed (Index): 134

Total Pages Failing   (Index): 0

Total Pages Processed (Other): 1130

Total Pages Processed (Seg)  : 0

Total Pages Failing   (Seg)  : 0

Total Pages Empty            : 306

Total Pages Marked Corrupt   : 3

Total Pages Influx           : 0

Highest block SCN            : 1559918 (0.1559918)

可以看到有兩個壞塊被檢測數122127。不過121122可能是實驗前就存在的壞塊。詳細資訊看後面的實驗分析,會有具體介紹。

c)         使用analyze命令

SQL> analyze table departments validate structure cascade;

analyze table departments validate structure cascade

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 4, block # 121)

ORA-01110: data file 4: '/u01/app/oracle/oradata/dblzc/users01.dbf'

更多的檢查工具就不一一介紹了。下面使用rman blockrecover命令進行恢復。

6.       執行恢復

執行恢復命令

RMAN> blockrecover datafile 4 block 121;

RMAN> blockrecover datafile 4 block 122;

RMAN> blockrecover datafile 4 block 127;

再次檢視一下departments表看看資料是否成功恢復

SQL> select * from departments;

 

DEPARTMENT_ID DEPARTMENT_NAME                MANAGER_ID LOCATION_ID

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

           10 Administration                        200        1700

           20 Marketing                             201        1800

           50 Shipping                              124        1500

           60 IT                                    103        1400

           80 Sales                                 149        2500

           90 Executive                             100        1700

          110 Accounting                            205        1700

          190  contracting                                     1700

 

8 rows selected.

可以看到資料被成功恢復!

二、        實驗分析

1.       問題一如何判斷壞塊的位置

在文件中診斷壞塊部分我們說道,我破壞了一個快127,在檢索的時候遇到了122,和121

這兩個壞塊。現在我們來看看這兩個壞塊分別位於哪個表所在的段中

SQL> select owner,block_id,segment_name from dba_extents where tablespace_name='USERS' AND block_id=121;

OWNER   BLOCK_ID SEGMENT_NAME

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

HR           121 DEPARTMENTS

SQL> select owner,block_id,segment_name from dba_extents where tablespace_name='USERS' AND block_id=122;

no rows selected

可看到121這個壞塊也屬於departments這個段中。至於122為啥沒找到這個,我分析了一下結果是。。。。。。嘿嘿,不知道。

你可能會問我,為什麼剛才在使用select * from departments; 命令時就看到一個壞塊呢,這是因為departments這個表當前的資料只佔用了127 一個塊,在檢索資料時也就只檢索了這一個塊。所以沒有報錯。

2.       問題二在bbed工具中使用find查詢命令時找不到目標字串

   a)可能是因為資料在修改提交後的資料被儲存在資料庫快取記憶體中沒有寫入資料檔案

這時候可以執行一次檢查點事件

Alter system checkpoint;

這種情況就不演示了

b)        offset的值低於當前current offset的值。

這種情況在這裡給大家模擬一下

1)        scott使用者下新建一個test測試表

SQL> desc test;

 Name                                      Null?    Type

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

 TSCN                                               CHAR(10)

 

SQL> show user;

USER is "SCOTT"

2)        向其中插入兩條資料

SQL> insert into test values('&var');

Enter value for var: ab

old   1: insert into test values('&var')

new   1: insert into test values('ab')

1 row created.

 

SQL> r

  1* insert into test values('&var')

Enter value for var: cd

old   1: insert into test values('&var')

new   1: insert into test values('cd')

1 row created.

檢視插入的資料

SQL> select * from test;

TSCN

----------

ab

cd

3)        檢視建立的測試表的file_id,以及block_id

SQL> select file_id,block_id,bytes from dba_extents where segment_name='TEST' AND wner='HR';

 

   FILE_ID   BLOCK_ID      BYTES

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

         4         65      65536

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

 

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

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

                                  68

                                  68

4)        使用bbed工具檢視塊資訊

在獲得我們想要的資訊之後現在我們可以進入bbed檢視對應塊中的資料了

BBED> set dba 4,68

        DBA             0x01000044 (16777284 4,68)

設定當前操作塊為68,使show命令看一下當前的引數設定是否正確

BBED> show all

        FILE#           4

        BLOCK#          68

        OFFSET          0

        DBA             0x01000044 (16777284 4,68)

        FILENAME        /u01/app/oracle/oradata/dblzc/users01.dbf

        BIFILE          bifile.bbd

        LISTFILE        /home/oracle/bbed_test/filelinux.log

        BLOCKSIZE       8192

        MODE            Edit

        EDIT            Unrecoverable

        IBASE           Dec

        OBASE           Dec

        WIDTH           80

        COUNT           512

        LOGFILE         log.bbd

        SPOOL           No

5)        查詢一行資料的offset

BBED> find /c ab

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 68               Offsets: 8178 to 8191           Dba:0x01000044

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

 61622020 20202020 20200406 a91b

 

 <32 bytes per line>

 

BBED> dump /v offset 8178

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 68      Offsets: 8178 to 8191  Dba:0x01000044

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

 61622020 20202020 20200406 a91b     l ab        ...

 

 <16 bytes per line>

可以看到test表中第一行的值正常顯示。

6)        查詢第二行記錄的offset

現在,我們檢視第二行記錄的值。

BBED> find /c cd

BBED-00212: search string not found

沒有找到,怎麼會沒有找到呢?難道是dba地址設錯了?現在我們show 命令看一下詳細資訊

BBED> show all

        FILE#           4

        BLOCK#          68

        OFFSET          8178

        DBA             0x01000044 (16777284 4,68)

        FILENAME        /u01/app/oracle/oradata/dblzc/users01.dbf

        BIFILE          bifile.bbd

        LISTFILE        /home/oracle/bbed_test/filelinux.log

        BLOCKSIZE       8192

        MODE            Edit

        EDIT            Unrecoverable

        IBASE           Dec

        OBASE           Dec

        WIDTH           80

        COUNT           512

        LOGFILE         log.bbd

        SPOOL           No

從上面我們可以看到dba的設定沒有錯誤啊,再細看,看到沒用紅色標出的部分。沒錯,offsets的值發生了變化,第一次我們show 命令的時候是0而我們第二次show的時候是8178

你或許會問,既然都是在一個塊上,find的查詢和offset查詢又有什麼關係呢?

這就要關聯到block的結構了。向塊中儲存資料時,是從下往上寫入,先寫入的資料在下面,後寫入的值在上面。而且後寫入的資料也就是在上面的資料的offset值要小於先寫入的。

find命令查詢資料的方式是從current offset開始向下查詢。由於在我find一條記錄是offset的值已經變為8178,大於第二條記錄的offset。所以當我查詢第二條記錄時find會從offset=8178 開始先下搜尋。這樣自然就無法找到後加入的記錄的值了。

既然瞭解了,就不用我多說了,只需要把offset的值設為0,就不怕找不到了。

7)        重設offset的值

BBED> set offset 0

        OFFSET          0

 

BBED> find /c cd

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 68               Offsets: 8164 to 8191           Dba:0x01000044

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

 63642020 20202020 20202c01 010a6162 20202020 20202020 0406a91b

 

 <32 bytes per line>

可以看到第二條記錄的offset值小於第一條記錄。

再看一下從 offset81648191之間的資料

BBED> dump/v offset 8164 count 27

 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)

 Block: 68      Offsets: 8164 to 8190  Dba:0x01000044

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

 63642020 20202020 20202c01 010a6162 l cd        ,...ab

 20202020 20202020 0406a9            l         ..

 

 <16 bytes per line>

可以看到第一天插入的記錄的值位於第二條插入記錄的值得後面。

最終成功找到了資料!

三、        實驗小結

總結一點,使用rman blockrecover 恢復塊是一定要有備份的,要有歸檔日誌。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26723566/viewspace-742657/,如需轉載,請註明出處,否則將追究法律責任。

相關文章