1. 背景:

oracle坏块分为逻辑坏块和物理坏块,逻辑坏块通常是由于oracle bug引起的,有时报ora-600错;物理坏块则由于硬件或者os、内存等引起的。这里主要研究物理坏块,分为索引坏块和表坏块两大类

2. 表坏块

1. 生成坏块:

我们可以通过oracle自带的工具bbed来管理物理数据文件和块block

10g可以直接通过命令安装bbed

cd $ORACLE_HOME/rdbms/lib

make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed

然后在PATH里将$ORACLE_HOME/rdbms/lib加上

 

11g及以上的版本需要拷贝10g的三个文件,此文件已附在文末

cp  bbedus.msb $ORACLE_HOME/rdbms/mesg

cp  sbbdpt.o  ssbbded.o $ORACLE_HOME/rdbms/lib

cd $ORACLE_HOME/rdbms/lib

make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed


select file#||' '||name||' '||bytes from v$datafile;

 

vi dbfiles.txt

1 /oracle10/oradata/dgtest/system01.dbf 471859200

2 /oracle10/oradata/dgtest/undotbs01.dbf 146800640

3 /oracle10/oradata/dgtest/sysaux01.dbf 450887680

4 /oracle10/oradata/dgtest/users01.dbf 5242880

5 /oracle10/oradata/dgtest/dgtest01.dbf 104857600

6 /oracle10/oradata/dgtest/test01.dbf 104857600

 

vi bbed_parameter.txt

blocksize=8192

listfile=/oracle10/dbfiles.txt

mode=edit

 


bbed parfile= bbed_parameter.txt

 

密码:blockedit

 

BBED> show all

image.png

info

image.png

生成坏块:

(1)先确认某张表所在的表空间和块号

select dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid),id from test1;

select segment_type,SEGMENT_NAME,PARTITION_NAME,HEADER_FILE,HEADER_BLOCK,tablespace_name from dba_segments where owner='TESTBBED'  order by  SEGMENT_NAME;

(2)进入bbed,modify块

modify 1000 file 6 block 13

(3)此时检测坏块,有三种方式

a. dbv

dbv  file=/oracle10/oradata/dgtest/test01.dbf blocksize=8192

image.png

b. bbed verify

image.png

c. rman

RMAN> backup validate datafile 6;

*检查整个库

backup  validate database;

 

此时会把corrupt的块记录到v$database_block_corruption中

select * from v$database_block_corruption;

image.png

(4)确认corrupt的段名和对象

由file#和block#确认segment名

SELECT SEGMENT_NAME,PARTITION_NAME,SEGMENT_TYPE FROM DBA_EXTENTS WHERE FILE_ID = 6 and 13 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1;

image.png

analyze table test1 validate structure cascade online;

image.png

清空缓存:

alter system flush buffer_cache;

报ora-01578或ora-01115错

image.png

image.png

2. 修复坏块

(1)若有物理备份,恢复后数据可能完整,也可能有丢失

list backupset;

image.png

blockrecover datafile 6 block 13;

image.png

dbv检查

image.png

(2)若无备份,数据可能有丢失

坏块中的数据一定丢失,其他好块中的数据可以通过跳过坏块的方式抢救

image.png

alter system set events '10231 trace name context forever,level 10'; ---设置跳过坏块

image.png

可以通过expdp/impdp truncate表的方式使得表恢复读写

expdp testbbed/test  directory=DATA_PUMP_DIR tables=test1 dumpfile=test1.dmp

 

impdp testbbed/test  directory=DATA_PUMP_DIR tables=test1 dumpfile=test1.dmp table_exists_action=truncate

 

truncate之后block不再是corrupted了,此时

alter system  set events '10231 trace name context off';

image.png

image.png

(3) 对于分区表我们修复的方式有两种

a. 将整个分区exchange到同结构的表中

create table test_partition_BAK as select * from test_partition where 1=2;

alter table test_partition exchange partition  p2  with table test_partition_BAK;

select count(*) from test_partition partition(p2); ---0条

此时再按照普通表的方式 跳过坏块 对test_partition_BAK进行expdp/impdp

最后再次将分区与不同表交换

alter table test_partition exchange partition  p2  with table test_partition_BAK;

注意:exchange分区会使得分区表分区索引失效,exchange后需要重建p2分区的索引才行

select status, INDEX_NAME,PARTITION_NAME  from user_ind_partitions;

image.png

alter index IDX_TEST_PARTITION rebuild partition p2  parallel 8 online;

b. 跳过坏块,直接将分区expdp/impdp,导入分区使用append

alter system set events '10231 trace name context forever,level 10';

expdp testbbed/test  directory=export tables=test_partition:p2 dumpfile=test_partition.dmp logfile=test_partition.log

alter table test_partition truncate partition p2;

impdp testbbed/test  directory=export dumpfile=test_partition.dmp table_exists_action=append

select count(*)from test_partition partition(p2);

 

3. 索引坏块

如果坏块出现在索引上,可能会出现如下错误

image.png

 

SELECT SEGMENT_NAME,PARTITION_NAME,SEGMENT_TYPE FROM DBA_EXTENTS WHERE FILE_ID = 18 and 195 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1;

经过检查发现此索引出现了坏块

(1)索引需要重建

但是如果我们按照下面的语句重建索引:

普通表:

alter index IDX_TEST1 rebuild;

在dba_segment 中会出现temporary segment,segment_name由file#.blockid构成

image.png

无法释放空间,需要我们手动释放或者修复

exec dbms_space_admin.segment_drop_corrupt('TEST',6,475);   表空间名 ,file#, blockid

SQL> select ts# from v$tablespace where name='TEST';

     TS#

----------

       7

alter session set events 'immediate trace name DROP_SEGMENTS level 8';   8等于表空间number+1

 

这种情况下生成的temporary段较难清除,故如果索引出现坏块,建议drop索引之后,在create索引,此时没有临时段产生

drop index IDX_TEST1;

create index IDX_TEST1 on test1(id);

但是分区索引经测试,不会有临时段存留,可以直接rebuild

alter index IDX_test_partition rebuild partition P1 online parallel 8;

(2)若有物理备份,可以直接通过rman修复此block

blockrecover datafile 6 block 475;

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐