-- 诊断数据库
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
RMAN> list failure;
修改上面原来high的故障的优先级到low
RMAN> change failure 402 priority low;
再次查询将查不到low的故障
RMAN> list failure;
但可以指定查询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);
end;
/
--查询坏块:
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
cc number;
begin
dbms_repair.fix_corrupt_blocks(
'LKPSPF',
'TB_ORDERS',
fix_count=>cc
);
dbms_output.put_line(cc);
end;
/
--只能跳过坏块,使用skip_corrupt_blocks过程。
SQL> declare
cc number;
begin
dbms_repair.skip_corrupt_blocks(
schema_name=>'LKPSPF',
object_name=>'TB_ORDERS'
);
dbms_output.put_line(cc);
end;
/
--此时,存在坏块的表可以使用,但坏块中记录丢失了。
select count(1) from LKPSPF.TB_ORDERS;
66545839
--坏块还在数据文件中,仍就不能使用rman备份。
RMAN> backup datafile '/../../.DBF';
--此时,需要把存在坏块的表中的数据使用ctas方式迁移到其他表中。然后删除有坏块的表。再次执行rman备份:备份成功。
RMAN> backup datafile '/../../.DBF';
-- 附坏块查询 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日志文件
RMAN> run {
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,
C.FILE#,
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
UNION
SELECT NULL OWNER,
NULL SEGMENT_TYPE,
NULL SEGMENT_NAME,
NULL PARTITION_NAME,
C.FILE#,
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;