1. 数据块/文件损坏快速处理预案
1.1 坏块问题
【故障现象】
session报错异常退出,alert和trace报错显示存在block corruption:
ORA-01578: ORACLE data block corrupted (file # 7, block # 3)
ORA-01110: data file 7: '/oracle/oradata/trgt/tools01.dbf'
ORA-01578: ORACLE data block corrupted (file # 2, block # 235)
ORA-01110: data file 2: '/oracle/oradata/trgt/undotbs01.dbf'
【可能故障原因】
物理磁盘损坏
逻辑错误
a) 启用归档备份
【应急措施】
1. 一般来说,在启用归档的情况下,大部分block级别的corruption都可以通过block recover进行恢复,并不一定需要进行数据库整库恢复;
2. 出现报错信息后,建议对数据文件先进行backup validate检查,将在v$database_block_corruption视图中显示检查到的所有坏块信息;
3. 使用block recover命令对坏块进行单独或全部修复
发现坏块
SQL> select count(*) from scott.tb_tmp;
select count(*) from scott.tb_tmp
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 133)
ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
执行backup validate检查数据文件
RMAN> backup validate datafile 6;
时间允许情况下,建议对全库进行检查
RMAN> backup validate database;
检查validate结果
SQL> select * from v$database_block_corruption;
FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
6 153 1 0 CORRUPT
6 143 1 0 CORRUPT
6 133 1 0 CORRUPT
使用block recover进行修复
RMAN> blockrecover datafile 6 block 133; -- 单块修复
RMAN> blockrecover corruption list; -- 对视图中所有坏块修复
b) 未启用归档备份
【应急措施】
1. 如果数据库没有启用归档和备份,意味这坏块无法进行修复;
2. 检查坏块所在对象,如果是索引对象则可以进行删除重建,如果是表对象并且存在日常备份,考虑进行导入恢复;
3. 如果坏块发生在表对象上并且没有任何备份,意味着该部分数据将丢失,考虑能否通过业务恢复;
4. 如果无法通过业务恢复,可将该部分数据丢弃,将剩余数据重建一张新表使用。
发现坏块
SQL> select count(*) from scott.tb_tmp;
select count(*) from scott.tb_tmp
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 133)
ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
执行backup validate检查数据文件
RMAN> backup validate datafile 6;
时间允许情况下,建议对全库进行检查
RMAN> backup validate database;
检查validate结果
SQL> select * from v$database_block_corruption;
FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
6 153 1 0 CORRUPT
6 143 1 0 CORRUPT
6 133 1 0 CORRUPT
检查坏块所在对象
SELECT tablespace_name,
segment_type,
owner,
segment_name,
partition_name
FROM dba_extents
WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1;
l 如果坏块所在对象为索引,直接进行删除重建可以解决;
l 如果坏块所在对象为表,检查能否通过日常导出备份或业务恢复。
标记和跳过坏块
a) 新建repair table
BEGIN
DBMS_REPAIR.ADMIN_TABLES (
TABLE_NAME => 'REPAIR_TABLE',
TABLE_TYPE => dbms_repair.repair_table,
ACTION => dbms_repair.create_action,
TABLESPACE => '&TABLESPACE_NAME');
END;
b) 检查坏块并记录到repair table
set serveroutput on
DECLARE num_corrupt INT;
BEGIN
num_corrupt := 0;
DBMS_REPAIR.CHECK_OBJECT (
SCHEMA_NAME => '&OWNER',
OBJECT_NAME => '&TABLE',
partition_name => '&PARTITION_NAME',
REPAIR_TABLE_NAME => 'REPAIR_TABLE',
corrupt_count => num_corrupt);
DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));
END;
Select * from REPAIR_TABLE;
c) 标记坏块并设置为查询跳过
DECLARE num_fix INT;
BEGIN
num_fix := 0;
DBMS_REPAIR.FIX_CORRUPT_BLOCKS (
SCHEMA_NAME => '&OWNER',
OBJECT_NAME=> '&TABLE',
partition_name => '&PARTITION_NAME',
OBJECT_TYPE => dbms_repair.table_object,
REPAIR_TABLE_NAME => 'REPAIR_TABLE',
FIX_COUNT=> num_fix);
DBMS_OUTPUT.PUT_LINE('num fix: ' || to_char(num_fix));
END;
BEGIN
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS (
SCHEMA_NAME => '&OWNER',
OBJECT_NAME => '&TABLE',
OBJECT_TYPE => dbms_repair.table_object,
FLAGS => dbms_repair.skip_flag);
END;
/
d) CTAS重建新表