客户在做RMAN备份的时候总是报错,于是客户用DBV校验了文件,发现有坏块.因为以前都做过RMAN备份,刚刚做就出现这类的问题.于是就叫我们去解决.以下是这个问题的解决步骤:
R:\oracle\hisdb>dbv file=DLSYY BLOCKSIZE=8192 DBVERIFY: Release 10.2.0.1.0 - Production on 星期一 5月 21 21:02:08 Copyright (c) 1982, 2005, Oracle. All rights reserved. DBVERIFY - 开始验证: FILE = DLSYY 页 3334278 标记为损坏 Corrupt block relative dba: 0x0172e086 (file 5, block 3334278) Bad check value found during dbv: Data in bad block: type: 6 format: 2 rdba: 0x0172e086 last change scn: 0x0000.1d6e043f seq: 0x3 flg: 0x06 spare1: 0x0 spare2: 0x0 spare3: 0x0 consistency value in tail: 0x043f0603 check value in block header: 0xc478 computed block checksum: 0x800 DBVERIFY - 验证完成 检查的页总数: 4194302 处理的页总数 (数据): 2195170 失败的页总数 (数据): 0 处理的页总数 (索引): 1961275 失败的页总数 (索引): 0 处理的页总数 (其它): 32789 处理的总页数 (段) : 0 失败的总页数 (段) : 0 空的页总数: 5067 标记为损坏的总页数: 1 流入的页总数: 0 最高块 SCN : 691673568 (0.691673568)
可以看到坏块的位置在块3334278上面.我们查询这个块所在地对象,可以看到是在表IP_MDREQUEST_BAK上面.
SQL> select *from V$DATABASE_BLOCK_CORRUPTION; FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO ---------- ---------- ---------- ------------------ --------- 5 3334278 1 0 CHECKSUM SQL> select segment_name,SEGMENT_TYPE from dba_extents where FILE_ID=5 2 and 3334278 between BLOCK_ID and BLOCK_ID+BLOCKS-1; SEGMENT_NAME SEGMENT_TYPE -------------------------------------------------------------------------- ----------------- IP_MDREQUEST_BAK TABLE SQL> drop table dlsyy.IP_MDREQUEST_BAK purge; 表已删除。
把这个表删除了之后,然后再次做DBV校验,发现还是有坏块,坏块的位置还在刚才那个块上,此时查询,这个块不在任何segment上面.
SQL> select segment_name,SEGMENT_TYPE from dba_extents where FILE_ID=5 2 and 3334278 between BLOCK_ID and BLOCK_ID+BLOCKS-1; 未选定行
解决办法:
1.此时这个块应该只是checksum坏了,我们只需要把checksum修改成正确的值就行了.
2.建一个新的表,给这个表插入数据,一直到插入到坏的块报错为止.
这里我选择了使用第二种方法来解决这个问题.
SQL> create table test tablespace DLSYY as select * from dba_data_files; 表已创建。
建完表后,我们可以使用下列循环来扩展这个表的尺寸.因为我们默认建完表分配都是64K.所以下面是用64K来扩展这个表.在扩展到同时,我们去开一个会话去监控坏块所处的对象,如果坏块进入到了当前所建的对象,我们就可以终止该循环语句.
BEGIN for i in 1..1000000 loop EXECUTE IMMEDIATE 'alter table test allocate extent (DATAFILE '||'''R:\ORACLE\HISDB\DLSYY||'SIZE 64K) '; end loop; end ; / SQL> select segment_name,SEGMENT_TYPE from dba_extents where FILE_ID=5 2 and 3334278 between BLOCK_ID and BLOCK_ID+BLOCKS-1; SEGMENT_NAME SEGMENT_TYPE -------------------------------------------------------------------------- ----------------- TEST TABLE
[注]:关闭数据文件的自动扩展属性.
接下来我们建立一个触发器,当我们插入数据,如果到达了块3334278的时候,就抛出一个异常,
create or replace trigger trigger_trg_curr_fix after insert on test for each row declare nblock_id number; begin select dbms_rowid.rowid_block_number(:new.rowid) into nblock_id from dual; if nblock_id=3334278 then raise_application_error(-20001,'curroption block format'); end if; end;
最后我们就多开几个session来循环执行插入,当到达触发器所在地块号的时候,就抛出了异常,此时我们的块就被我们格式化掉了.
SQL>begin for i in 1..100000000 loop for j in 1..1000 loop insert into test(FILE_NAME,FILE_ID,TABLESPACE_NAME) values('SSSSSSSSSSSSSSS',i,'xXXXXXXXXXXX'); end loop; commit; end loop; end; /
再一次使用DBV校验工具进行校验,坏块消失,备份正常!
R:\oracle\hisdb>dbv file=DLSYY blocksize=8192 DBVERIFY: Release 10.2.0.1.0 - Production on 星期一 5月 21 22:36:53 2012 Copyright (c) 1982, 2005, Oracle. All rights reserved. DBVERIFY - 开始验证: FILE = DLSYY DBVERIFY - 验证完成 检查的页总数: 4194302 处理的页总数 (数据): 2218006 失败的页总数 (数据): 0 处理的页总数 (索引): 1938676 失败的页总数 (索引): 0 处理的页总数 (其它): 32553 处理的总页数 (段) : 0 失败的总页数 (段) : 0 空的页总数: 5067 标记为损坏的总页数: 0 流入的页总数: 0 最高块 SCN : 692302023 (0.692302023)
参考文档:
How to Format Corrupted Block Not Part of Any Segment [ID 336133.1]
Post a Comment