壞塊分為物理壞塊和邏輯壞塊,前者是硬件問題產生,后者是oracle內部數據有問題,本次試驗針對后者。
需要歸檔模式,步驟
1 create tablespace test 1m (table t1, insert) 2 RMAN>backup tablespace test 3 模擬壞塊 4 DBV 5 ANALYZE TABLE 6 RMAN BACKUP 7 EXP 8 DBMS_REPAIR 9 BLOCKRECOVER
1,sys用戶下創建表空間
SYS@jsce>create tablespace tbs1 datafile 'e:\tbs1.dbf' size 1m; --大小1M,容易填滿(現在突然有疑惑:為什么要填滿,才能制造壞塊?)
在tbs1中創建表tb1,數據來源是scott.emp
SYS@jsce>create table tb1 tablespace tbs1 as select * from scott.emp;
雙倍遞增插入表tb1,來源也是其自己
SYS@jsce>insert into tb1 select * from tb1; --這里是select出來的東西插入到表,沒有關鍵字values
已創建15行。
SYS@jsce>insert into tb1 select * from tb1;
已創建30行。
SYS@jsce>insert into tb1 select * from tb1;
已創建60行。
在插滿之后,不要忘記commit,否則oracle不能shutdown,最后確認一下插入的數據量“15360”
》給表增加索引,后面查詢有壞塊之后,壞塊帶來損失的數據ORPHAN_TABLE;
SYS@jsce>create index i1 on tb1(ename);
索引已創建。
SYS@jsce>alter system checkpoint; --這一步是將插入的數據作檢查點寫入數據文件,下一步就要通過ultraedit修改數據文件,制造壞塊。
系統已更改。
備注:如果表字段沒有設置not null必輸項,並且表字段很多,那么可以指定字段來插入一部分,比如emp表
insert into emp(empno,ename,sal) values(22,'sumsen',8900);
2,rman備份表空間tbs1,得到優良備份(下面還原使用)
RMAN> backup tablespace tbs1 tag=ok;--增加tag
3,shutdown之后,通過ultraedit修改數據文件 --修改的時候不要開頭部,那里是數據文件名稱,有可能導致oracle啟動失敗
修改,保存之后,數據文件目錄會多出一個TBS1.DBF.bak,說明修改過了,不知道為何
啟動oracle再次查詢報錯,壞塊產生 --這里的select 是遇到第一個壞塊就報錯,因此如果有多個壞塊,也是報出一個錯誤信息,需要用下面的REPAIR_TABLE查詢所有的壞塊。
4,用dbv檢測
這里僅僅給出壞塊數,沒有給出壞塊號和文件號
5,使用 ANALYZE TABLE
SYS@jsce>analyze table tb1 validate structure;
6,rman的備份和exp導出有壞塊的表空間
exp導出sys下的
E:\Documents and Settings\xs>exp userid='sys/sys as sysdba' file=e:\exptbs1.dmp tablespaces=tbs1
導出表空間沒有問題
導出表有壞塊報錯
rman提示超過壞塊限制
通過設置壞塊最大數來繼續備份
RMAN> run{set maxcorrupt for datafile 3 to 10;backup tablespace tbs1 tag=bad;} 要寫在一塊,讓rman知道是一個事務
因為最大壞塊設置為了10,tbs1有兩個壞塊,可以通過備份
7,包DBMS_REPAIR
exec DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',1,1,'USERS');--表數據
exec DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE',2,1,'USERS');--索引數據
檢查壞塊:dbms_repair.check_object , 這里的schema_name是用戶,比如我在sys下建立的表空間,這里就是sys,
object_name是表不是表空間(查詢的時候報錯也是通過select * from tb1)
declare
cc number;
begin
dbms_repair.check_object(schema_name => 'SYS',object_name => 'TB1',corrupt_count => cc);
dbms_output.put_line(a => to_char(cc)); --這里a=>不明不白,可以去掉
end;
看到這里用dbms_repair.check,檢查的結果corrupt_count=2,有2個塊損壞,和dbv的結果一致。
check完之后,在我們剛在創建的REPAIR_TABLE中查看塊損壞詳細信息:
SELECT object_name, relative_file_id, block_id, marked_corrupt, corrupt_description, repair_description, CHECK_TIMESTAMP from repair_table;
得到4個結果,不過就兩個塊(33,69),只是時間不一樣,不解?
我們注意看MARKED_CORRUPT的值,這里經過check_object后,已經標識為TRUE了。(?)
》使用包的skip_corrupt_blocks過程來跳過壞塊
exec dbms_repair.skip_corrupt_blocks(schema_name => 'SYS',object_name => 'TB1',flags => 1);
損失了15360-15020=340 條數據
》處理index上的無效鍵值;dump_orphan_keys
declare
cc number;
begin
dbms_repair.dump_orphan_keys(schema_name => 'SYS',object_name => 'I1',object_type => 2,
repair_table_name => 'REPAIR_TABLE',orphan_table_name => 'ORPHAN_TABLE',key_count => CC);
end;
之后查詢數據,我們根據這個結果來考慮是否需要rebuild index(?)
和上面的損失數目一樣
9 BLOCKRECOVER 恢復壞塊--前提是壞塊事先有備份
RMAN> blockrecover from tag=ok datafile 3 block 33,69;--必須要指定壞塊號
之后查詢tb1,恢復
這時候dbv檢測也為0
18:10 更新,使用oracle內部事件
再次破壞了數據文件,可是查詢時候仍然不報錯,想到是前面執行了讓oracle跳過壞塊的過程
exec dbms_repair.skip_corrupt_blocks(schema_name => 'SYS',object_name => 'TB1',flags => 1);
直接將flag=>2
SELECT tablespace_name, segment_type, owner, segment_name
FROM dba_extents
WHERE file_id = 3
and 35 between block_id AND block_id + blocks - 1 --這里 35 between不懂
ALTER SYSTEM SET EVENTS='10231 trace name context forever,level 10' ;
之后
SQL> ALTER SYSTEM SET EVENTS='10231 trace name context off' ;
系統已更改。
刪除表空間
SYS@jsce>drop tablespace tbs1 including contents and datafiles; --表空間物理文件也被刪除
之后導入
演示省略。