-- 診斷資料庫
1.檢視故障
list failure [all | critical | high | low | closed | failnum[,failnum,...]]
[ exclude failure failnum[,failnum,...]]
[ detail]
删除資料檔案6
[oracle@dbserver ~]$ rm -fr /u01/app/oracle/oradata/orcl/ts_inventory01.dbf
列出故障,預設顯示優先級為high的故障。
rman> list failure;
列出故障明細
rman> list failure detail;
2.故障修複建議
advise failure
注意,advise failure 必須在同一個視窗中緊跟 list failure 才能正常使用。
rman> advise failure;
上面指令系統會給出修複故障的腳本,檢視腳本内容如下:
$ more /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_1651608170.hm
3.修複故障
repair failure
[ using advise option integer ]
[ noprompt | review]
注意,repair failuer 必須在同一視窗中緊跟 advise failure 後才能正常使用。
修複預覽
rman> repair failure preview;
修複故障,noprompt 表示不提示直接修複,不帶将會出現修複提示。
rman> repair failure noprompt;
4.修改故障優先級和關閉故障 change failure
修改上面原來high的故障的優先級到low
rman> change failure 402 priority low;
再次查詢将查不到low的故障
但可以指定查詢low級别的故障
rman> list failure low;
rman> list failure all;
關閉故障
rman> change failure 402 closed;
5.故障恢複相關視圖
v$ir_failure: 包含所有檢測到的故障,包含已經關閉的故障。
v$ir_manual_checklist: 相關故障的手動修複建議
v$ir_repair: 相關故障的自動修複步驟
v$ir_failure_set: 存放故障id和其修複建議id的關聯
6.主動監控資料庫
使用em健康監控或rman指令 validate database
rman> validate database; --11g才開始提供的指令
11g之前使用dbv工具進行資料庫檔案校驗(支援離線校驗):
$ dbv file=/u01/app/oracle/oradata/orcl/ts_inventory01.dbf
11g之前還可以使用 dbms_repair 包中相關的函數進行壞塊的處理
7.關于資料塊校驗的幾個參數
db_ultra_safe: 整合了db_block_checking,db_block_checksum,db_lost_write_protect三個參數,屬于11g的新參數。
db_block_checking: 啟動對資料庫塊的檢查,預設為false,即使關閉也會強制檢查system表空間的資料塊。
db_block_checksum: 修改塊資料時加入并且驗證塊的校驗位,預設為typical
db_lost_write_protect: 在data guard中保護資料成功寫入實體備庫,預設為typical
8.塊媒體恢複
恢複條件:
①開啟歸檔
②存在全備或0級備份
③存在有效的閃回日志
v$database_block_corruption: 存放資料中所有壞塊資訊
資料庫存在壞塊時,預設是不允許進行備份的,是以需要經常檢查備份的有效性。
可以允許跳過壞塊進行備份,同時把壞塊資訊寫入 v$database_block_corruption中:
rman> run {
set maxcorrupt for datafile 6 to 1000;
backup datafile 6;
}
修複一個塊:
recover datafile 6 block 131;
修複多個塊:
recovery datafile 2 block 43
datafile 2 block 70
datafile 6 block 110;
修複所有壞塊:
recover corruption list;
修複好的塊将不再出現在 v$database_block_corruption.
9.檢視診斷知識庫(11g開始才推出adr)
使用 adrci 工具
$ adrci
adrci> help --檢視adrci的幫助資訊
adrci> show incident; --檢視所有的事件資訊
adrci> show alert; --檢視所有的報警資訊
也可以通過v$diag_info檢視診斷資訊
sql> select*from v$diag_info;
11g中診斷資訊相關目錄參數不能修改,統一設定到adr_home/ 目錄下
10.健康監控
視圖v$hm_check列出所有健康監控的内容
健康檢查可以使用em(em中助手中心裡的檢查器)
也可以調用dbms_hm.run_check執行健康檢查
tab$ 表示資料庫中的所有基表
sql> exec dbms_hm.run_check('dictionary integrity check','mycheck',0,'table_name=tab$');
sql> set long 20000
sql> select dbms_hm.get_run_report('mycheck') from dual;
在adrci中檢視健康檢查
adrci> show home
adrci> set home diag/rdbms/orcl/orcl
adrci> create report hm_run mycheck
adrci> show report hm_run mycheck
-- 壞塊修複示例 --
-- 用内部事件來屏蔽全表掃描的時候忽略壞塊。
alter system set events='10231 trace name context for ever,level 10'
-- 給定一個表空間,并在此表空間下建立維修表
exec dbms_repair.admin_tables(table_name => 'repair_table',table_type => dbms_repair.repair_table,action => dbms_repair.create_action,tablespace => 'users');
-- 對指定的<schema>.<object>檢查并确認其中壞塊(如果同時指定 partition_name 也可以進行分區級别檢查):
set serveroutput on
var num_corrupt number;
exec :num_corrupt :=0;
exec dbms_repair.check_object(schema_name => 'sys',object_name => 'impdp_stats',repair_table_name => 'repair_table',corrupt_count => :num_corrupt);
exec dbms_output.put_line('number corrupt: ' || to_char(:num_corrupt));
-- 對檢查出的壞塊,可選擇性地進行标記:
select block_id, corrupt_type, corrupt_description from repair_table;
-- rem mark the identified blocks as corrupted ( soft corrupt - reference note 1496934.1 )
var num_fix number;
exec :num_fix := 0;
exec dbms_repair.fix_corrupt_blocks(schema_name => 'sys',object_name => 'impdp_stats',object_type => dbms_repair.table_object,repair_table_name => 'repair_table',fix_count => :num_fix);
exec dbms_output.put_line('num fix: ' || to_char(num_fix));
-- 在将來進行dml操作時,對壞塊進行跳過處理:
exec dbms_repair.skip_corrupt_blocks (schema_name => '&schema_name',object_name => '&object_name',object_type => dbms_repair.table_object,flags => dbms_repair.skip_flag);
-- 注意:
使用dbms_repair通路壞塊後,index scan可能會出現報錯,碰到這類報錯,你需要重建這些索引。如果是唯一索引,那麼相同資料的重新插入可能會報ora-1錯誤。
如果在 dbms_repair.skip_flag 已經啟用後,希望将跳塊标記清除以重新通路壞塊,可以在執行dbms_repair.skip_corrupt_blocks時,使用dbms_repair.noskip_flag進行參數設定。
使用dbms_repair.skip_corrupt_blocks來跳塊僅能針對出現ora-1578報錯的那些壞塊情況。如果是針對其它類型壞塊,就需要額外執行admin_tables, check_object 和fix_corrupt_blocks來對壞塊進行标記處理。
在執行過skip_corrupt_blocks後,如果需要将表中的壞塊進行清理,可以對表使用”alter table <name> move”,而不是重建或truncate掉它。然後使用dbms_repair.noskip_flag去除掉跳塊标記即可。注意,壞塊中的資料會被丢失掉。
-----------------------------------------------------------------------------
-- 壞塊問題
-- db file verify(dbv) 工具
-- 外部指令,實體媒體資料結構完整性檢查;
-- 隻能用于資料檔案(offline或online),不支援控制檔案和重做日志檔案的塊檢查;
-- 也可以驗證備份檔案(rman的copy指令備份或作業系統cp指令備份);
-- dbv file=data01.dbf blocksize=8192;
-- 解決壞塊過程
找出資料檔案上的表、分析出出現壞塊的表、找出所有的壞塊:
找出檔案編号:
select * from dba_data_files t where t.file_name = '/u01/../../.dbf';
找出檔案上的表:
select distinct t.segment_name , t.segment_type from dba_extents t where t.file_id = '12' order by t.segment_name, t.segment_type;
--使用select count(1) from tablename的辦法,找出哪些表上有壞塊。
sql> select count(1) from schema.table;
error at line 1:
ora-01578: oracle data block corrupted (file # 12, block # 608129)
ora-01110: data file 12: '/u01/../../.dbf'
從上面查詢可知表tablename上有壞塊,但可能不止一個壞塊,是以我使用dbv找出這個表上所有壞塊。辦法是,找出表的segment_id:
select s.ts#, t.header_file, t.header_block , t.owner, t.* from dba_segments t
left join v$tablespace s
on t.tablespace_name = s.name
where t.segment_name = 'table_name';
6.5.1118066
在伺服器上,執行dbv工具:
dbv logfile=/home/oracle/dbv_lkpspf_.log userid=ahern/oracle segment_id=6.5.1118066 -- 分析指令執行的結果
-- 1、使用rman修複壞塊,但因為歸檔丢失,無法恢複。
rman> recover datafile 18 block 58630;
-- 2、使用 sys.dbms_repair修複:fix_corrupt_blocks修複失敗、skip_corrupt_blocks忽略壞塊、導出可以用資料、删除壞塊的表。
--建repaire表:repair_table
sql> begin
dbms_repair.admin_tables(
table_type=>dbms_repair.repair_table,
action=>dbms_repair.create_action,
tablespace=>'users'
);
end;
/
-- 檢查壞塊:
sql> declare
cc number;
begin
dbms_repair.check_object(
schema_name=>'lkpspf',
object_name=>'tb_orders',
object_type=>dbms_repair.table_object,
repair_table_name=>'repair_table',
corrupt_count=>cc
dbms_output.put_line(cc);
--查詢壞塊:
sql> col repair_description for a50
sql> select block_id, repair_description from repair_table;
608129 mark block software corrupt
608193 mark block software corrupt
-- 與dbv分析結果相同。
--使用 fix_corrupt_blocks 恢複壞塊,但沒有成功。
sql> declare
dbms_repair.fix_corrupt_blocks(
'lkpspf',
'tb_orders',
fix_count=>cc
);
dbms_output.put_line(cc);
--隻能跳過壞塊,使用skip_corrupt_blocks過程。
cc number;
begin
dbms_repair.skip_corrupt_blocks(
schema_name=>'lkpspf',
object_name=>'tb_orders'
--此時,存在壞塊的表可以使用,但壞塊中記錄丢失了。
select count(1) from lkpspf.tb_orders;
66545839
--壞塊還在資料檔案中,仍就不能使用rman備份。
rman> backup datafile '/../../.dbf';
--此時,需要把存在壞塊的表中的資料使用ctas方式遷移到其他表中。然後删除有壞塊的表。再次執行rman備份:備份成功。
-- 附壞塊查詢 sql
rman>backup check logical validate datafile n ; -- 檢查資料檔案是否包含壞塊,同時并不産生實際的備份輸出
-- 也可以直接使用rman的指令:backup validate check logical database;
rman target / nocatalog
rman> spool log to '/u01/../dbbak/rmanlog.log'; -- 指定輸出rman日志檔案
allocate channel d1 type disk;
allocate channel d2 type disk;
allocate channel d3 type disk;
allocate channel d4 type disk;
backup validate check logical database;
};
-- 結合v$database_block_corruption視圖更友善
select * from v$database_block_corruption;
-- --if v$database_block_corruption contains rows please run this query to find the objects that contains the corrupted blocks:
select e.owner,
e.segment_type,
e.segment_name,
e.partition_name,
c.file#,
greatest(e.block_id, c.block#) corr_start_block#,
least(e.block_id + e.blocks - 1, c.block# + c.blocks - 1) corr_end_block#,
least(e.block_id + e.blocks - 1, c.block# + c.blocks - 1) -
greatest(e.block_id, c.block#) + 1 blocks_corrupted,
null description
from dba_extents e, v$database_block_corruption c
where e.file_id = c.file#
and e.block_id <= c.block# + c.blocks - 1
and e.block_id + e.blocks - 1 >= c.block#
union
select s.owner,
s.segment_type,
s.segment_name,
s.partition_name,
header_block corr_start_block#,
header_block corr_end_block#,
1 blocks_corrupted,
'segment header' description
from dba_segments s, v$database_block_corruption c
where s.header_file = c.file#
and s.header_block between c.block# and c.block# + c.blocks - 1
select null owner,
null segment_type,
null segment_name,
null partition_name,
greatest(f.block_id, c.block#) corr_start_block#,
least(f.block_id + f.blocks - 1, c.block# + c.blocks - 1) corr_end_block#,
least(f.block_id + f.blocks - 1, c.block# + c.blocks - 1) -
greatest(f.block_id, c.block#) + 1 blocks_corrupted,
'free block' description
from dba_free_space f, v$database_block_corruption c
where f.file_id = c.file#
and f.block_id <= c.block# + c.blocks - 1
and f.block_id + f.blocks - 1 >= c.block#
order by file#, corr_start_block#;
-- 執行下面語句的結果來自于上面的查詢
select tablespace_name, segment_type, owner, segment_name
from dba_extents
where file_id = &fileid
and &blockid between block_id and block_id + blocks - 1;