ORACLE壞塊總結2

aaqwsh發表於2011-03-12
五.如何查詢壞塊所含的資料表名稱和資料的rowid
5.1.首先肯定知道那個資料檔案壞了,查出該檔案的file_id,relative_fno,tablespace_name
 
 利用dba_data_files可以查詢file_id(整個資料庫唯一序號),RELATIVE_FNO(相對一個表空間內的序號)
 
5.2.找到壞塊的ID(可以執行dbverify實現),假設找到的壞塊ID為1234。
5.3.執行下面的查詢,根據,壞塊的file_id,block id查詢該塊對應的owner,segment_type,
segment_name等資訊
 
   select owner,file_id,segment_name, segment_type, block_id, blocks
  from dba_extents
  where file_id=13 and block_id<=1234 and (block_id + blocks- 1) >= 1234;
 
 
5.4.根據壞塊的file_id,owner,segment_name,block_id,如果是資料表的話,用下面的查詢來得到對應壞塊的rowid
 
 假設owner : DAVE
 
     segment_name: BL
 
     file_id    : 13
 
     block_id   : 162
 
 執行下面的查詢來獲得該塊所含的rowid(如果沒有索引,可能就不能用下面的方式了):
 
select /*+ index(DAVE, i_test)?*/ rowid
 from DAVE.BL
 where dbms_rowid.rowid_to_absolute_fno(rowid,'DAVE','BL')=13
 and dbms_rowid.rowid_block_number(rowid)=162;  
 
六,如何模擬壞塊
 
DBA的基本知識,製造壞塊的方法很多的,可以用ultraedit,也可以用dd命令,同時也呆以用orapatch工具
 
6.1 orapatch工具:
$orapatch open tools001.dbf write
patch>set hex --要用十六進位制
patch>display 177 --orapatch以512位元組為工作模式,假定想破壞第11個block即為:8k/512*11+1(file header)
patch>find 00400003 --選一個要編輯的點
patch>modify 00400002 --破壞
patch>exit
 
6.2用編輯器開啟datafile以8192位元組為一大小(db的block是8192)
下面是一個block的開始的20個位元組和結尾的4個位元組
06 02 00 00 08 00 c0 02 6c 43 0d 00 00 00 01 02
00 00 00 00 -- block head
06 02 6c 43 -- block tail這裡有scn(6c 43)的情況和block (06)的型別(01)和head的seq: 0x01對應,只要改block尾部的4個位元組中的或block開始的對應位元組任何一個就一定會有ora-1578,但如果資料庫有ora-1578的error不一定是這樣引起的
btw:UE不是很好用winhex吧不錯喔
 
6.3 BBED工具
 
 
 

七. 如何利用dbms_repair來標記和跳過壞塊
但是當資料量很大,或7*24的系統時,我們使用dbms_repair來處理。dbms_repair是從oracle8i開始提供的。
 
準備工作:
createtablespaceblockdatafile'/u01/block.dbf'size5M;
createtableDMMtablespaceblockasselect*fromall_tables;
commit;
CREATEINDEXindx_dmmonDMM(TABLE_NAME);
selectcount(*)fromDMM;
 COUNT(*)
----------
12896
 
 
7.1.建立管理表:
SQL> conn sys/admin as sysdba;
已連線。
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
 
7.2.檢查壞塊:dbms_repair.check_object
 
/* Formatted on 2009-12-16 23:41:32 (QP5 v5.115.810.9015) */
Set serveroutput on;
DECLARE
  cc NUMBER;
BEGIN
  DBMS_REPAIR.check_object(schema_name=>'SYS',--注意此處是使用者名稱
                            object_name    =>'DMM',
                            corrupt_count  =>cc);
  DBMS_OUTPUT.put_line(TO_CHAR(cc));
END;
 
正常情況下輸入為0.
 
如果有壞塊,可以在建立的REPAIR_TABLE中檢視塊損壞資訊:  
 
/* Formatted on 2009-12-17 13:18:19 (QP5 v5.115.810.9015) */
SELECT  object_name,
        relative_file_id,
        block_id,
        marked_corrupt,
        corrupt_description,
        repair_description,
        CHECK_TIMESTAMP
 FROM  repair_table;                                                                                                                                                                                                      
                                                                                                                                          
 
注意:在8i下,check_object只會檢查壞塊,MARKED_CORRUPT為false,故需要執行第三步:定位壞塊,fix_corrupt_blocks定位,修改MARKED_CORRUPT為true,同時更新CHECK_TIMESTAMP。9i以後經過check_object,MARKED_CORRUPT的值已經標識為TRUE了。所以可以直接進行第四步了。
 
 
7.3.定位壞塊:dbms_repair.fix_corrupt_blocks    
只有將壞塊資訊寫入定義的REPAIR_TABLE後,才能定位壞塊。
/* Formatted on 2009-12-17 13:29:01 (QP5 v5.115.810.9015) */
DECLARE
  cc  NUMBER;
BEGIN
  DBMS_REPAIR.fix_corrupt_blocks(schema_name  =>'SYS',
                                  object_name  =>'DMM',
                                  fix_count    =>cc);
  DBMS_OUTPUT.put_line(a=>TO_CHAR(cc));
END;
 
 
7.4.跳過壞塊:
我們前面雖然定位了壞塊,但是,如果我們訪問table:
SQL> select count(*) fromSYS.DMM;
 
 
ORA-01578: ORACLE資料塊損壞(檔案號14,塊號154)
ORA-01110:資料檔案14: 'D: \BLOCK.DBF'
 
還是會得到錯誤資訊。這裡需要用skip_corrupt_blocks來跳過壞塊:
 
/* Formatted on 2009-12-17 13:30:17 (QP5 v5.115.810.9015) */
execdbms_repair.skip_corrupt_blocks(schema_name=>'SYS',object_name=>'DMM',flags=>1);
 
 
SQL> select count(*) from SYS.DMM;
 
 COUNT(*)
----------
    12850
丟失了12896-12850=46行資料。
 
 
7.5.處理index上的無效鍵值;dump_orphan_keys
 
/* Formatted on 2009-12-17 13:34:55 (QP5 v5.115.810.9015) */
DECLARE
  cc  NUMBER;
BEGIN
  DBMS_REPAIR.dump_orphan_keys(schema_name        =>'SYS',
                                object_name        =>'INDX_DMM',
                                object_type        =>2,
                                repair_table_name  =>'REPAIR_TABLE',
                                orphan_table_name  =>'ORPHAN_TABLE',
                                key_count          =>CC);
END;
 
通過以下命令可以知道丟失行的資訊:
SQL> SELECT * FROM ORPHAN_TABLE;
 
我們根據這個結果來考慮是否需要rebuild index.
7.6.重建freelist:rebuild_freelists
 
/* Formatted on 2009-12-17 13:37:57 (QP5 v5.115.810.9015) */
execdbms_repair.rebuild_freelists(schema_name=>'SYS',object_name=>'DMM');
 
八.設定內部事件使exp跳過壞塊
我們可以用設定event的方法來處理壞塊:先模擬出壞塊,然後用dbv檢查,此時,不用dbms_repair,而用下面的方法:
 
8.1.先exp該表試驗一下
在這種情況下,如果有備份,需要從備份中恢復,如果沒有備份,那麼壞塊部分的資料肯定要丟失了
在這個時候匯出是不允許的:
E:\>exp system/admin file=t.dmp tables=t
 
報錯如下:
即將匯出指定的表通過常規路徑...
. .正在匯出表T
EXP-00056:遇到ORACLE錯誤1578
ORA-01578: ORACLE資料塊損壞(檔案號4,塊號35)
ORA-01110:資料檔案4: 'E:\ORACLE\ORADATA\EYGLE\BLOCK.DBF'
匯出成功終止,但出現警告。
 
8.2.對於不同的情況需要區別對待,如果損失不是資料而是重要的oracle內部資訊,則不能用set event。
 
首先你需要檢查損壞的物件,使用以下SQL:
/* Formatted on 2009-12-17 14:00:42 (QP5 v5.115.810.9015) */
SELECT  tablespace_name,
        segment_type,
        owner,
        segment_name
 FROM  dba_extents
 WHERE  file_id=4AND35BETWEENblock_idANDblock_id+blocks-1;
 

 

8.3.如果損失的是資料,ok,可以設定內部事件,使exp跳過這些損壞的block
 
10231事件指定資料庫在進行全表掃描時跳過損壞的塊
ALTER SYSTEM SET EVENTS='10231 trace name context forever,level 10' ;
然後我們可以匯出未損壞的資料
E:\> exp system/admin file=t.dmp tables=t
即將匯出指定的表通過常規路徑...
. .正在匯出表T 8036行被匯出
在沒有警告的情況下成功終止匯出。
然後我們可以drop table,recreate,然後匯入資料

8.4.重建表,再匯入
SQL> connect sys/admin as sysdba
已連線。
SQL> drop table t;
表已丟棄。
E:\>imp system/admin file=t.dmp tables=t
.正在將system的物件匯入到system
. .正在匯入表"T" 8036行被匯入
成功終止匯入,但出現警告。
E:\>exit
SQL> select count(*) from t;
COUNT(*)
----------
8036
 
完成資料恢復.
 
損失的行數可以從2個行數相減計算:
8192 - 8036 = 156行資料
 
 
8.5如果要取消events設定,做以下操作:
1.如果你在初始化引數中設定的
註釋之
2.如果在命令列設定的
alter system set events='10231 trace name context off';

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

相關文章