[OCP學習筆記]043-07-處理資料庫損壞--模擬實驗(2)

xuqingwei發表於2010-06-06

4.使用工具進行修復

這裡,我們嘗試採用多種工具來對損壞的資料塊進行修復。前文中我構建了擁有4個壞塊的表空間test,資料檔案為test01.dbf,大小1MB。為了簡化操作,我們備份了他的一個副本test01.bak。以下操作可在每個實驗前獨立進行,以確保實驗樣本的一致性,且彼此之間不會產生衝突。

sys@STUDY> host copy test01.bak test01.dbf

sys@STUDY>alter tablespace test online;

Tablespace altered.

sys@STUDY>alter system flush buffer_cache;

System altered.

l 使用BlockRecover...corruption list進行修復

前文中,我們使用RMAN對修改前的正確的test表空間進行了備份,對出現壞塊後的test表空間進行了validate

在做BMR之前,首先確定需要恢復的表空間是否有備份存在。

RMAN> list backup of tablespace "TEST";

List of Backup Sets

===================

BS Key Type LV Size Device Type Elapsed Time Completion Time

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

35 Full 648.00K DISK 00:00:01 2010-06-05 21:15:56

BP Key: 32 Status: AVAILABLE Compressed: NO Tag: TAG20100605T211555

Piece Name: C:ORACLEPRODUCT10.2.0FLASH_RECOVERY_AREASTUDYBACKUPSET2010_06_05O1_MF_NNNDF_TAG20100605T211555_60NMJCWB_.BKP

List of Datafiles in backup set 35

File LV Type Ckp SCN Ckp Time Name

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

14 Full 1921865 2010-06-05 21:15:55 C:ORACLEPRODUCT10.2.0ORADATASTUDYTEST01.DBF

其次,確認需要恢復的資料塊資訊已經記錄到V$BACKUP_CORRUPTION檢視中。

sys@STUDY>select * from v$database_block_corruption;

FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO

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

14 28 1 0 CHECKSUM

14 20 1 0 FRACTURED

14 16 1 0 FRACTURED

執行BMR操作進行恢復。

RMAN> blockrecover corruption list;

Starting blockrecover at 2010-06-05 21:40:09

using channel ORA_DISK_1

channel ORA_DISK_1: restoring block(s) from datafile copy C:ORACLEPRODUCT10.2.0FLASH_RECOVERY_AREASTUDYDATAFILEO1_MF_TEST_60NML16T_.DBF

starting media recovery

media recovery complete, elapsed time: 00:00:03

Finished blockrecover at 2010-06-05 21:40:14

再次進行驗證

RMAN> backup validate tablespace "TEST";

Starting backup at 2010-06-05 21:43:14

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafile backupset

channel ORA_DISK_1: specifying datafile(s) in backupset

input datafile fno=00014 name=C:ORACLEPRODUCT10.2.0ORADATASTUDYTEST01.DBF

channel ORA_DISK_1: backup set complete, elapsed time: 00:00:02

Finished backup at 2010-06-05 21:43:16

再次查詢V$DATABASE_BLOCK_CORRUPTION確定壞塊已經被修復。

sys@STUDY>select * from v$database_block_corruption;

no rows selected

類似的,大家可以嘗試使用映象來進行壞塊的恢復,兩者過程大致相同。

l 使用BlockRecover...File#...Block#進行恢復

RMAN> blockrecover datafile 14 block 16, 20, 24, 28;

Starting blockrecover at 2010-06-05 21:54:13

using channel ORA_DISK_1

channel ORA_DISK_1: restoring block(s) from datafile copy C:ORACLEPRODUCT10.2.0FLASH_RECOVERY_AREASTUDYDATAFILEO1_MF_TEST_60NML16T_.DBF

starting media recovery

media recovery complete, elapsed time: 00:00:07

Finished blockrecover at 2010-06-05 21:54:21

dbv file=test01.dbf

DBVERIFY: Release 10.2.0.1.0 - Production on Sat Jun 5 21:55:14 2010

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

DBVERIFY - Verification starting : FILE = test01.dbf

DBVERIFY - Verification complete

Total Pages Examined : 128

Total Pages Processed (Data) : 53

Total Pages Failing (Data) : 0

Total Pages Processed (Index): 8

Total Pages Failing (Index): 0

Total Pages Processed (Other): 17

Total Pages Processed (Seg) : 0

Total Pages Failing (Seg) : 0

Total Pages Empty : 50

Total Pages Marked Corrupt : 0

Total Pages Influx : 0

Highest block SCN : 1921792 (0.1921792)

修復完畢。

l 使用DBMS_REPAIR軟體包進行恢復

首先確定在16202428資料塊中存放記錄的數量。

sys@STUDY>select count(rowid) from t1 where dbms_rowid.rowid_block_number(rowid) in (16, 20, 24, 28);

COUNT(ROWID)

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

130

建立repair_tableorphan_table,用於存放壞塊和索引中對應的孤鍵記錄。

BEGIN

DBMS_REPAIR.ADMIN_TABLES (

TABLE_NAME => 'REPAIR_TABLE',

TABLE_TYPE => dbms_repair.repair_table,

ACTION => dbms_repair.create_action,

TABLESPACE => 'TEST');

END;

/

BEGIN

DBMS_REPAIR.ADMIN_TABLES (

TABLE_NAME => 'ORPHAN_KEY_TABLE',

TABLE_TYPE => dbms_repair.orphan_table,

ACTION => dbms_repair.create_action,

TABLESPACE => 'TEST');

END;

/

使用CHECK_OBJECT過程檢測壞塊

SET SERVEROUTPUT ON

DECLARE

num_corrupt INT;

BEGIN

num_corrupt := 0;

DBMS_REPAIR.CHECK_OBJECT (

SCHEMA_NAME => 'SYS',

OBJECT_NAME => 'T1',

REPAIR_TABLE_NAME => 'REPAIR_TABLE',

CORRUPT_COUNT => num_corrupt);

DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));

END;

/

查詢repair_table,檢視檢測到的壞塊的資訊:

sys@STUDY>select BLOCK_ID, CORRUPT_TYPE, MARKED_CORRUPT, REPAIR_DESCRIPTION from repair_table;

BLOCK_ID CORRUPT_TYPE MARKED_COR REPAIR_DESCRIPTION

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

16 6148 TRUE mark block software corrupt

20 6148 TRUE mark block software corrupt

24 6148 TRUE mark block software corrupt

28 6148 TRUE mark block software corrupt

這裡marked_corrupt被標記為true,應該是系統在執行CHECK_OBJECT過程中自動完成了FIX_CORRUPT_BLOCKS。如果被標記為flase,需要再執行FIX_CORRUPT_BLOCKS來完成壞塊的標記工作。

sys@STUDY>DECLARE

2 num_fix INT;

3 BEGIN

4 num_fix := 0;

5 DBMS_REPAIR.FIX_CORRUPT_BLOCKS (

6 SCHEMA_NAME => 'SYS',

7 OBJECT_NAME=> 'T1',

8 OBJECT_TYPE => dbms_repair.table_object,

9 REPAIR_TABLE_NAME => 'REPAIR_TABLE',

10 FIX_COUNT=> num_fix);

11 DBMS_OUTPUT.PUT_LINE('num fix: ' || TO_CHAR(num_fix));

12 END;

13 /

num fix: 0

PL/SQL procedure successfully completed.

標記了0個壞塊,說明CHECK_OBJECT完成了標記工作。

雖然我們對壞塊進行了標記,但由於索引並未損壞,因此透過索引來訪問資料表,仍然可能引發ORA-01578錯誤。

sys@STUDY>select * from t1 where table_name='REPCAT$_TEMPLATE_REFGROUPS';

select * from t1 where table_name='REPCAT$_TEMPLATE_REFGROUPS'

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 14, block # 28)

ORA-01110: data file 14: 'C:ORACLEPRODUCT10.2.0ORADATASTUDYTEST01.DBF'

"REPCAT$_TEMPLATE_REFGROUPS"對應的記錄存放在第28塊中,透過索引來訪問時,發生錯誤。

使用DUMP_ORPHAN_KEYS過程來儲存壞塊中的索引鍵值,存放到ORPHAN_KEY_TABLE中。

sys@STUDY> SET SERVEROUTPUT ON

1 DECLARE

2 num_orphans INT;

3 BEGIN

4 num_orphans := 0;

5 DBMS_REPAIR.DUMP_ORPHAN_KEYS (

6 SCHEMA_NAME => 'SYS',

7 OBJECT_NAME => 'ID_T1',

8 OBJECT_TYPE => dbms_repair.index_object,

9 REPAIR_TABLE_NAME => 'REPAIR_TABLE',

10 ORPHAN_TABLE_NAME=> 'ORPHAN_KEY_TABLE',

11 KEY_COUNT => num_orphans);

12 DBMS_OUTPUT.PUT_LINE('orphan key count: ' || TO_CHAR(num_orphans));

13 END;

14 /

PL/SQL procedure successfully completed.

注意:如果表有多個索引,需要為每個索引執行DUMP_ORPHAN_KEYS操作。

sys@STUDY>select count(*) from orphan_key_table;

COUNT(*)

----------

130

和存放在162024284個壞塊中的記錄數量相當。

如果表空間採用的是資料字典管理的話,空塊將被記錄在freelists連結串列中。如果壞塊發生在FREELIST列表中的中部,則FREELIST列表後面的塊都無法訪問。為此,我們需要執行REBUILD_FREELISTS過程來修改FREELISTS

sys@STUDY>BEGIN

2 DBMS_REPAIR.REBUILD_FREELISTS (

3 SCHEMA_NAME => 'SYS',

4 OBJECT_NAME => 'T1',

5 OBJECT_TYPE => dbms_repair.table_object);

6 END;

7 /

BEGIN

*

ERROR at line 1:

ORA-10614: Operation not allowed on this segment

ORA-06512: at "SYS.DBMS_REPAIR", line 400

ORA-06512: at line 2

這裡我們採用的是ASSM來進行表空間管理,所以無需執行REBUILD_FREELISTS操作。

執行SKIP_CORRUPT_BLOCKS過程,是後續DML操作跳過壞塊

sys@STUDY>BEGIN

2 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS (

3 SCHEMA_NAME => 'SYS',

4 OBJECT_NAME => 'T1',

5 OBJECT_TYPE => dbms_repair.table_object,

6 FLAGS => dbms_repair.skip_flag);

7 END;

8 /

PL/SQL procedure successfully completed.

由於資料和索引仍然存在不一致的問題,因此必須重建索引。

sys@STUDY>alter index id_t1 rebuild;

Index altered.

sys@STUDY>select table_name from t1 where table_name='REPCAT$_TEMPLATE_REFGROUPS';

TABLE_NAME

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

REPCAT$_TEMPLATE_REFGROUPS

注意一點,重建索引一點要先DROP,然後再CREATE,使用REBUILD的方式,重建的資料來源來自索引,仍然會導致問題的產生。

sys@STUDY>drop index id_t1;

Index dropped.

sys@STUDY>create index id_t1 on t1(table_name);

Index created.

sys@STUDY>select table_name from t1 where table_name='REPCAT$_TEMPLATE_REFGROUPS';

no rows selected

sys@STUDY>select count(*) from t1;

COUNT(*)

----------

1605

sys@STUDY>select count(*) from dba_tables;

COUNT(*)

----------

1738

我們發現在標識SKIP_CORRUPT_BLOCKS的過程中,一共少了133個記錄。然而,ORPHAN_KEY_TABLE中僅記錄了130條記錄。中間有3個記錄丟失了!

[@more@]《第07章 處理資料庫損壞》學習筆記.pdf

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

相關文章