首页 > Linux操作系统 > Linux操作系统 > 坏块---ORA_1258
1、找出所有受影响的对象
vi checkdb.sh
rman target / nocatalog <
allocate channel d1 type disk;
allocate channel d2 type disk;
allocate channel d3 type disk;
allocate channel d4 type disk;
backup validate check logical database;
}
exit;
EOF
nohup sh checkdb.sh > checkdblog &
得到RMAN检查,会将所有问题的数据块放入v$database_block_corruption;
select * from v$database_block_corruption;
得到具体问题的对象信息。
create table tmp_dba_extents as select * from dba_extents;
create index ix_tmp_dba_extents on tmp_dba_extents(file_id,block_id,blocks);
create table tmp_dba_segments as select * from dba_segments;
create table corrupted_objects
as
select owner,segment_name,partition_name,segment_type,1 file#,1 block#
from dba_extents
where 1=2;
declare
cursor C1 is select file#,block#,blocks
from v$database_block_corruption;
begin
for r1 in C1 loop
for r2 in 1..r1.blocks loop
insert into corruped_objects
select owner,segment_name,partition_name,segment_type,r1.file#,r1.block#+r2-1
from tmp_dba_extents
where file_id=r1.file#
and (r1.block#+r2-1) between block_id and block_id +blocks -1;
if sql%nofound then
/* segment header block might be corrupt causing dba_extents not returning rows.*/
insert into corrupted_objects
select owner,segment_name,partition_name,segment_type,r1.file#,r1.block#
from tmp_dba_segments
where header_file=r1.file# and header_block=(r1.block#+r2-1);
end if;
commit;
end loop;
end loop;
end;
/
执行如下SQL,得到需要重建的表,索引,分区:
select distinct owner,segment_name,partition_name,segment_type
from corrupted_objects;
得到索引对应的表:
select distinct owner,index_name,table_name
from corrupted_objects c,dba_indexes i
where c.segment_name=i.index_name and c.segment_type like '%INDEX%';
和应用确认,是否表中数据需要恢复,如果不需要,直接truncate清空该表。
二、重建表
得到表定义的SQL:
exp username/password compress=n rows=n,tables('TAB1','TAB2',...)file=exp.dmp
imp username/password INDEXFILE=table.sql file=exp.dmp rows=n
建表SQL在table.sql中,修改表名建立新的表,索引可等在数据全部导入后创建。
三、导入数据
确认对应表、表分区的大小
select segment_name,sum(bytes)/1024/1024
from dba_segments
where segment_name in(
select segment_name from corrupted_objects c
where c.segment_type like '%TABLE%')
group by segment_name;
对于总表小于50G的分区表,可以直接重建全表,因为针对分区操作复杂。
在sqlplus中,执行:
1) --允许跳坏块
alter session set events '10231 trace name context forever,level 10';
2) --允许session级别的并行操作
alter session enable parallel dml;
3)--做并行插入
insert /*+ append parallel(person_tmp 4) */ into person_tmp nologging
select /* + parallel( a 4)*/ * from person a;
commit;
4) --查看对应表的并行度确认没有修改,并行度不为1,会导致查询的时候
执行计划的不正确,影响数据库性能。
select degree from dba_tables where table_name='PERSON_TMP';
注意commit后再查看新表中记录和已有表的记录是否一致。
5) --修改新表
alter table rename 表名 to 新表名;
针对单个分区
如果分区表较大超过50G,个别分区有问题,可仅对单个分区进程处理,步骤如下:
1) --允许跳过坏块
alter session set events '10231 trace name context forever,level 10';
2)--允许session级别的并行操作
alter session enable parallel dml;
3)做并行插入
insert/*+ append parallel(person_tmp 4)*/ into person_tmp nologging
select /* + parallel(a 4)*/ * from person partition(par_2004_01) a;
-- par_2004_01为corrutped_objects的分区名
4) --确认两边数据一致后。删除原分区上的数据。
delete from person partition(par_2004_01);
commit;
5) --再将数据插入回来
insert /*+ append parallel(person 4)*/ into person nologging
select /* parallel(a 4)*/ from person_tmp partition(par_2004_01)a;
commit;
from tmp_dba_segments
where header_file=r1.file# and header_block=(r1.block#+r2-1);
end if;
commit;
end loop;
end loop;
end;
/
四、建立索引
针对索引上有问题的块,而所在表上没有问题的块,可以直接重建索引。
alter index 索引名 rebuild online;
对该表,按照table.sql的定义新建索引,注意此前应该较旧表上的索引删除,
或者新建时修改新表上索引名。
五、无用数据清理
该过程中建的表可以drop掉
drop table tmp_dba_extents;
drop table tmp_dba_segments;
drop table corrupted_objects;
新表使用正常后,无用的旧表可以drop掉。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/23757700/viewspace-751948/ ,如需转载,请注明出处,否则将追究法律责任。