使用dbms_repair修復塊損壞

it_newbalance發表於2012-10-11

使用dbms_repair修復塊損壞的例子

dbms_repair是從oracle8i開始提供的。

我們可以用設定event的方法來處理壞塊:

但是當資料量很大,或7*24的系統時,這樣的方法就不是很合適了。這裡我們使用dbms_repair來處理。

SQL> create tablespace block datafile 'D:\oracle\oradata\oracle9i\block.dbf' size 5M;

Tablespace created

SQL> connect dlinger/dlinger
Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0
Connected as dlinger

QL> create table test tablespace block as select * from all_tables;

Table created

SQL> insert into test select * from test;

806 rows inserted

SQL> insert into test select * from test;

1612 rows inserted

SQL> insert into test select * from test;

3224 rows inserted

SQL> insert into test select * from test;

6448 rows inserted

SQL> insert into test select * from test;

insert into test select * from test

ORA-01653: 表DLINGER.TEST無法通過128(在表空間BLOCK中)擴充套件

SQL> commit;

Commit complete

SQL> select count(*) from test;

  COUNT(*)
----------
     12896

SQL> create index i_test on test(table_name);

Index created

SQL> alter system checkpoint;

System altered


SQL> connect sys/sys as sysdba
已連線。
SQL> shutdown immediate
資料庫已經關閉。
已經解除安裝資料庫。
ORACLE 例程已經關閉。

--使用UltraEdit編輯block.dbf,修改幾個字元

SQL> startup
ORACLE 例程已經啟動。

Total System Global Area   72424008 bytes
Fixed Size                   453192 bytes
Variable Size              46137344 bytes
Database Buffers           25165824 bytes
Redo Buffers                 667648 bytes
資料庫裝載完畢。
資料庫已經開啟。
SQL> select count(*) from dlinger.test;
select count(*) from dlinger.test
                             *
ERROR 位於第 1 行:
ORA-01578: ORACLE 資料塊損壞(檔案號14,塊號160)
ORA-01110: 資料檔案 14: 'D:\ORACLE\ORADATA\ORACLE9I\BLOCK.DBF'


用dbv檢查:
C:\Documents and Settings\duanl>dbv file='D:\oracle\oradata\oracle9i\block.dbf'
blocksize=8192

DBVERIFY: Release 9.2.0.1.0 - Production on 星期二 8月 24 19:58:15 2004

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

DBVERIFY - 驗證正在開始 : FILE = D:\oracle\oradata\oracle9i\block.dbf
標記為損壞的頁160
***
Corrupt block relative dba: 0x038000a0 (file 14, block 160)
Bad check value found during dbv:
Data in bad block -
type: 6 format: 2 rdba: 0x038000a0
last change scn: 0x0000.0035f5c2 seq: 0x1 flg: 0x06
consistency value in tail: 0xf5c20601
check value in block header: 0x3681, computed block checksum: 0x5bb
spare1: 0x0, spare2: 0x0, spare3: 0x0
***



DBVERIFY - 驗證完成

檢查的頁總數         :640
處理的頁總數(資料):510
失敗的頁總數(資料):0
處理的頁總數(索引):0
失敗的頁總數(索引):0
處理的頁總數(其它):9
處理的總頁數 (段)  : 0
失敗的總頁數 (段)  : 0
空的頁總數            :120
標記為損壞的總頁數:1
匯入的頁總數           :0

使用dbms_repair包
1.建立管理表:
SQL> connect sys/sys as sysdba
Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0
Connected as SYS

SQL> exec DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',1,1,'USERS');

PL/SQL procedure successfully completed

SQL> exec DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE',2,1,'USERS');

PL/SQL procedure successfully completed


2.檢查壞塊:dbms_repair.check_object

SQL> declare
  2  cc number;
  3  begin
  4  dbms_repair.check_object(schema_name => 'DLINGER',object_name => 'TEST',cor
rupt_count => cc);
  5  dbms_output.put_line(a => to_char(cc));
  6  end;
  7  /
1

PL/SQL 過程已成功完成。      

看到這裡用dbms_repair.check,檢查的結果corrupt_count=1,有一個塊損壞,和dbv的結果一致。

check完之後,在我們剛在建立的REPAIR_TABLE中檢視塊損壞資訊:   

SQL> SELECT object_name, relative_file_id, block_id,marked_corrupt, corrupt_description, repair_description,                                                                                                                                               
  2  CHECK_TIMESTAMP from repair_table;                                                                                                                                                                                                                    
                                                                                                                                            
OBJECT_NAME    RELATIVE_FILE_ID   BLOCK_ID MARKED_CORRUPT CORRUPT_DESCRIPTION   REPAIR_DESCRIPTION           CHECK_TIMESTAMP
-------------- ---------------- ---------- -------------- --------------------- ---------------------------- ---------------
TEST                         14        160 TRUE                                 mark block software corrupt  2004-8-24 21:46

在這個table中,可以看到損壞的block的資訊,這裡的資訊和我們用dbv得到的一致。
我們這個實驗是在9i下模擬的,我們注意看MARKED_CORRUPT的值,這裡經過check_object後,已經標識為TRUE了。
所以可以直接進行第四步了。
按照oracle文件上的說法,在8i下,check_object只會檢查壞塊,MARKED_CORRUPT為false
需要使用第3步,fix_corrupt_blocks定位 ,修改MARKED_CORRUPT為true,同時更新CHECK_TIMESTAMP。
這裡我們經過實驗,確認在9i下跳過第3步,是完全可行的。
那麼8i是否需要執行第三步,我沒有實驗過,但推測應該是不可以跳過的。   

3.定位壞塊:dbms_repair.fix_corrupt_blocks      

只有將壞塊資訊寫入定義的REPAIR_TABLE後,才能定位壞塊。  
declare
cc number;
begin
dbms_repair.fix_corrupt_blocks(schema_name => 'DLINGER',object_name => 'TEST',fix_count => cc);
dbms_output.put_line(a => to_char(cc));
end;

4.跳過壞塊:


我們前面雖然定位了壞塊,但是,如果我們訪問table:
SQL> select count(*) from dlinger.dbblock;

select count(*) from dlinger.dbblock

ORA-01578: ORACLE 資料塊損壞(檔案號14,塊號154)
ORA-01110: 資料檔案 14: 'D:\ORACLE\ORADATA\ORACLE9I\BLOCK.DBF'

還是會得到錯誤資訊。   
這裡需要用skip_corrupt_blocks來跳過壞塊:

SQL> exec dbms_repair.skip_corrupt_blocks(schema_name => 'DLINGER',object_name => 'TEST',flags => 1);

PL/SQL procedure successfully completed

SQL> select count(*) from dlinger.test;

  COUNT(*)
----------
     12850


丟失了12896-12850=46行資料。

5.處理index上的無效鍵值;dump_orphan_keys

declare
cc number;
begin
dbms_repair.dump_orphan_keys(schema_name => 'DLINGER',object_name => 'I_TEST',object_type => 2,
repair_table_name => 'REPAIR_TABLE',orphan_table_name => 'ORPHAN_TABLE',key_count => CC);
end;
/

SQL> SELECT * FROM ORPHAN_TABLE;

SCHEMA_NAME    INDEX_NAME  IPART_NAME     INDEX_ID TABLE_NAME  PART_NAME    TABLE_ID KEYROWID               KEY                                        DUMP_TIMESTAMP
-------------- ----------- ------------ ---------- ----------- ---------- ---------- ---------------------- ------------------------------------------ --------------
DLINGER        I_TEST                        30258 TEST                        30257 AAAHYxAOwAAAIADA0A     *BAAAAAAMTE9HTU5SQ19HU0lJ/g                2004-8-25 22:1
DLINGER        I_TEST                        30258 TEST                        30257 AAAHYxAOwAAAIADAsA     *BAAAAAAMTE9HTU5SQ19HVExP/g                2004-8-25 22:1
..............................................

DLINGER        I_TEST                         30258 TEST                        30257 AAAHYxAOwAAAIADB0A     *BAAAAAAPTE9HTU5SX0xPQkZSQUck/g          2004-8-25 22:1
DLINGER        I_TEST                         30258 TEST                        30257 AAAHYxAOwAAAIADBYA     *BAAAAAAMTE9HTU5SX1RZUEUk/g              2004-8-25 22:1
DLINGER        I_TEST                         30258 TEST                        30257 AAAHYxAOwAAAIADAQA     *BAAAAAALTE9HTU5SX1VJRCT+                2004-8-25 22:1
DLINGER        I_TEST                         30258 TEST                        30257 AAAHYxAOwAAAIADAoA     *BAAAAAAMTE9HTU5SX1VTRVIk/g              2004-8-25 22:1

46 rows selected

和上面我們看到的損失的資料行數吻合。

我們根據這個結果來考慮是否需要rebuild index.

6.重建freelist:rebuild_freelists

SQL> exec dbms_repair.rebuild_freelists(schema_name => 'DLINGER',object_name => 'TEST');

PL/SQL procedure successfully completed

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

相關文章