一。.什么是数据库的坏块 首先我们来大概看一下数据库块的格式和结构——
数据库的数据块有固定的格式和结构,分三层 cache layer
,transaction layer
,data layer
。在我们对数据块进行读取写入操作的时候,数据库会对要读写的数据块做一致性的检查,其中包括数据块的类型、数据块的地址信息、数据块的SCN
号以及数据块的头部和尾部。如果发现其中有不一致的信息,那数据库就会标记这个数据块为坏块了。数据库的坏块分为两种,逻辑坏块和物理坏块。二.模拟坏块SQL> conn system
SQL> create tablespace corrupt datafile'C:corrupt.dbf' size 200k;
SQL> create table corrupt_tab tablespacecorrupt as select * from all_users;
SQL> alter table corrupt_tabmodify(user_id primary key);
SQL> selectextent_id,file_id,block_id,blocks from dba_extents
2
where wner='SYSTEM' andsegment_name='CORRUPT_TAB';
EXTENT_ID
FILE_ID
BLOCK_ID
BLOCKS
---------- ---------- ---------- ----------
0
8
17
8
上述查询说明,这个表具有一个区间EXTNET_ID 0
,位于8
号文件,从块号17
开始,大小为8
个块。SQL> conn / as sysdba
SQL> shutdown immediate;
用UE
编辑器模拟出物理或逻辑坏块。保存SQL> startup
SQL> select count(*) fromsystem.corrupt_tab;
COUNT(*)
----------
21
SQL> select * from system.corrupt_tab;
select * from system.corrupt_tab
*
第 1
行出现错误:
ORA-01578:
ORACLE 数据块损坏 (
文件号 8,
块号 20)
ORA-01110:
数据文件 8: 'C:CORRUPT.DBF'
由于corrupt_tab
表上有一个主键约束,从而使ORACLE
能够通过扫描索引(而不是表)对记录进行计数。第二条查询需要读取表本身,因此会失败并报ORA-01578:
错误查看警告文件Hex dump of (file 8, block 20) in tracefile
c

racleproduct10.2.0adminpdbudumppdb_ora_2248.trc
Corrupt block relative dba: 0x02000014(file 8, block 20)
Bad check value found during buffer read
Data in bad block:
type: 6 format: 2 rdba: 0x02000014
lastchange scn: 0x0000.0009e3b6 seq: 0x2 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0xe3b60602
check value in block header: 0x13b
computed block checksum: 0x5c66
Reread of rdba: 0x02000014 (file 8, block20) found same corrupted data
Sun May 18 23:11:18 2008
Corrupt Block Found
TSN = 9, TSNAME = CORRUPT
RFN = 8, BLK = 20, RDBA = 33554452
BJN = 51436, BJD = 51436, BJECT = CORRUPT_TAB, SUBOBJECT =
SEGMENT WNER = SYSTEM, SEGMENT TYPE = Table Segment
再次说明了相关文件以及数据块号,并且给出了一个重要信息OBJD = 51436
(属有这个坏块的对象号为51436
)SQL> selectowner,object_name,object_type from dba_objects where object_id=51436;
OWNER
OBJECT_NAME
OBJECT_TYPE
---------- ----------------------------------
SYSTEM
CORRUPT_TAB
TABLE
或SQL> selectowner,segment_name,segment_type from dba_extents where file_id=8 and
20between block_id and block_id+blocks;
OWNER
OBJECT_NAME
OBJECT_TYPE
---------- ----------------------------------
SYSTEM
CORRUPT_TAB
TABLE
三..DBVERIFY实用程序用于验证数据文件,手动备份。RNAM
的镜像拷贝。不能验证日志文件。控制文件。以及RMAN
的备份集。可以验证数据文件中的所有坏块。C:>dbv file=C:CORRUPT.DBF
以上验证说明CORRUPT.DBF
数据文件存在两个坏块12
、20
四.AYALYZE命令检查表或索引是否有坏块SQL>analyze table
validate structure;
SQL>analyze index validate structure;
SQL>analyze table validate structure cascade;
Cascade选项验证指定表及相关联的全部索引,对于大对象将是一个非常耗时的过程。
五.DBMS_REPAIR程序包
DBMS_REPAIR程序包是检查对象是否存在问题并使其再次可用的一组过程。
--创建REPAIR_CORRUPT_TAB表
exec dbms_repair.admin_tables(-
table_name=>'REPAIR_CORRUPT_TAB',-
table_type=>dbms_repair.repair_table,-
action=>dbms_repair.create_action);
--检测坏块,信息存入REPAIR_CORRUPT_TAB表
declare num_corrupt int;
begin
num_corrupt:=0;
dbms_repair.check_object(
schema_name=>'SYSTEM',
object_name=>'CORRUPT_TAB',
repair_table_name=>'REPAIR_CORRUPT_TAB',
corrupt_count=>num_corrupt);
dbms_output.put_line(num_corrupt);
end;
/
selectschema_name,object_name,relative_file_id,block_id,repair_description fromrepair_corrupt_tab;
--标记坏块
declare num_fix int;
begin
num_fix:=0;
dbms_repair.fix_corrupt_blocks(
schema_name=>'SYSTEM',
object_name=>'CORRUPT_TAB',
object_type=>DBMS_REPAIR.TABLE_OBJECT,
repair_table_name=>'REPAIR_CORRUPT_TAB',
fix_count=>num_fix);
end;
/
--忽略所有被标记为坏块的数据块
execdbms_repair.skip_corrupt_blocks('SYSTEM','CORRUPT_TAB');
结果
SQL> select * from system.corrupt_tab;
未选定行
SQL> select count(*) fromsystem.corrupt_tab;
COUNT(*)
----------
21
会话能够成功访问被影响的对象,不过受损的数据块中的数据将会丢失。这将导致不可预期的结果。
Alter index … rebuild online重新构建索引
DBMS_REPAIR程序包提供了一种不需要停机就可以使受损表可用的方式,但是代价却是丢失数据。决定使用这个程序包之前,需要考虑受损的范围、对业务的影响以及是否更适合采用还原与恢复的操作。
六.使用RMAN恢复坏块
RMAN备份可以在不停机的情况下进行块级的还原与恢复。并且可以用RMAN检测坏块。
SQL> conn system/oracle
SQL>=drop tablespace corrupt;
SQL> create tablespace corrupt datafile'C:corrupt.dbf' size 200k;
SQL> create table corrupt_tab tablespacecorrupt as select * from all_users;
SQL> alter table corrupt_tabmodify(user_id primary key);
SQL> selectextent_id,file_id,block_id,blocks from dba_extents
2
where wner='SYSTEM' andsegment_name='CORRUPT_TAB';
先来做一个CORRUPT2.DBF文件的备份。
RMAN> backup format 'C:corr.bak'datafile 'C:CORRUPT2.DBF' tag corr2;
SQL> conn / as sysdba
SQL> shutdown immediate;
依照前面的方法模拟出坏块。
SQL> select * from system.corrupt_tab2;
select * from system.corrupt_tab2
*
第 1 行出现错误:
ORA-01578: ORACLE 数据块损坏 (文件号 7, 块号 12)
ORA-01110: 数据文件 7: 'C:CORRUPT2.DBF'
已经出现坏块。此时再用RMAN备份
失败。
将RMAN中C:CORRUPT2.DBF文件中允许的坏块增加到100,只要坏块小于100就能备份成功。并在v$backup_corruption视图中生成所有坏块的记录。如果是镜像副本,则应该是v$copy_corruption.
RMAN>run{
Set maxcorrupt for datafile 7 to 100;
Backup datafile 7;}
恢复坏块
blockrecover datafile 7 block 12 from tagCORR2;
验证
C:>dbv file=C:CORRUPT2.DBF
SQL> select * from system.corrupt_tab2;