2016年03月09日 数据库类 浏览(64) 收藏

Oracle数据备份的时候发现了某个数据文件产生了逻辑坏块怎么办?

生产环境Oracle数据备份的时候发现了某个数据文件产生了逻辑坏块,检查该Corrupt block,上面并没有任何对象存在。怎么办?

最佳回答

建议参考:http://www.everycoding.com/coding/259.html

这里提供一个类似案例:

某次数据库的备份数据文件6,发现有坏块存在。

RMAN> backup datafile 6 format ‘E:\Backup\full_%s_%p’;
启动 backup 于 03-8月 -09
使用通道 ORA_DISK_1
通道 ORA_DISK_1: 启动全部数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
输入数据文件 fno=00006 name=G:\ORACLE\MM01.DBF
通道 ORA_DISK_1: 正在启动段 1 于 03-8月 -09
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: backup 命令 (ORA_DISK_1 通道上, 在 08/03/2009 21:36:58 上) 失败
ORA-19566: 超出损坏块限制 0 (文件 G:\ORACLE\MM01.DBF)


1)使用dbv检查

C:\>dbv file=G:\ORACLE\MM01.DBF blocksize=8192

DBVERIFY: Release 10.2.0.1.0 – Production on 星期一 8月 3 21:38:07 2009
Copyright (c) 1982, 2005, Oracle. All rights reserved.
DBVERIFY – 开始验证: FILE = G:\ORACLE\MM01.DBF
页 448000 标记为损坏
Corrupt block relative dba: 0x0186d600 (file 6, block 448000)
Bad check value found during dbv:
Data in bad block:
type: 0 format: 2 rdba: 0x0006d600
last change scn: 0×0000.00000000 seq: 0×1 flg: 0×05
spare1: 0×0 spare2: 0×0 spare3: 0×0
consistency value in tail: 0×00000001
check value in block header: 0×7106
computed block checksum: 0×11

dbv检查出坏块位于datafile 6 block 448000。


2)查询该坏块block 448000上面的object.

SQL> select OWNER,SEGMENT_NAME from dba_extents a where file_id=6 and 448000 between a.block_id and a.block_id+a.blocks;

OWNER SEGMENT_NAME
—————————— ————-

SQL>select tablespace_name from dba_free_space where (448000 between block_id and block_id+blocks ) and file_id=6;

TABLESPACE_NAME
——————————
MM

 该block属于空闲block,并不存在任何对象.

3)查询坏块所在datafile上已经分配的最大block.

SQL> select max(BLOCK_ID+blocks) from dba_extents a where tablespace_name=’MM’;
MAX(BLOCK_ID+BLOCKS)
——————–
46473

当前已经分配的最大block为46473,而损坏的block位于448000,如果直接做数据填充推进extent,会产生较大的事务和redo量.为避免,我们可以创建2张表(本案例为tmp_1,tmp_2),一张表(tmp_1)用来推进extent到邻近损坏的block,使得后创建的一张表tmp2尽可能挨近坏块.然后对tmp_2做数据填充,用来格式化损坏的block.这样可以以消耗最少的redo代价和压力来完成format block的目的。同时,在需要填充的表上(tmp_2)创建触发器,当待处理坏块被格式化后,马上自动停止填充.。


4)创建表tmp_1并推进extent

SQL> create table tmp_1 tablespace mm as select * from dba_data_files;
Table created

SQL> alter table tmp_1 allocate extent (datafile ‘g:\oracle\mm01.dbf’ size 3200M);
Table altered

SQL> select OWNER,SEGMENT_NAME from dba_extents a where file_id=6 and 448000 between a.block_id and a.block_id+a.blocks;

OWNER SEGMENT_NAME
—————————— ———– 

5)创建表tmp_2用以格式化坏块

SQL> create table tmp_2(id number,text char(2000)) tablespace mm;
Table created

SQL> alter table tmp_2 allocate extent (datafile ‘g:\oracle\mm01.dbf’ size 200M);
Table altered

SQL> select OWNER,SEGMENT_NAME from dba_extents a where file_id=6 and 448000 between a.block_id and a.block_id+a.blocks;

OWNER SEGMENT_NAME
—————————— ————
REP TMP_2 

 目前待扩充的表高水位线外已经包含坏块448000.


6)创建tmp_2上trigger,用于自动终止填充数据

create or replace trigger trigger_trg_curr_fix after insert on tmp_2 for each row
declare
nblock_id number;
begin
select dbms_rowid.rowid_block_number(:new.rowid) into nblock_id from dual;
if nblock_id=448000 then
raise_application_error(-20001,’curroption block format’);
end if;
end;

7)推进HWM以格式化坏块

SQL>begin
loop
insert into tmp_2 values(1,rpad(‘i’,1800,’*'));
commit;
end loop;
end;
/
ORA-20001: curroption block format
ORA-06512: 在 “REP.TRIGGER_TRG_CURR_FIX”, line 6
ORA-04088: 触发器 ‘REP.TRIGGER_TRG_CURR_FIX’ 执行过程中出错
ORA-06512: 在 line 3

至此,填充自动终止,坏块已经被格式化.做几次日志切换,然后用dbv再次检查数据文件,发现已经修复.接下来删除表tmp_1和tmp_2

感谢风之别鹤的贡献!
赞一下 0 人赞了本文