使用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 |