oracle 10g数据库坏块的处理记录
记录一次oracle数据库坏块的处理过程,包含了undo坏块和数据文件坏块,丢失部分数据。
前些天客户oracle 10g数据库发生的坏块处理,同事反应客户exp备份时出现exp-00056错误,exp数据的时候报错,其他表可以
从ora-01578可以看到文件号5的块号568107损坏了,第一反应就是使用rman 的blockrecover datafile 5 block 568107 修复,只是确认了下发现数据库没有在归档模式运行。看来是的丢失部分数据了。
查询了下568107上面的对象
select tablespace_name,segment_type,owner,segment_name from dba_extents where file_id=5 and 568107between block_id AND block_id + blocks - 1;
经过开发确认,损坏的表为历史表,可以忍受丢失部分数据。
下面要重建下这张表,用ctas方式同样的错误
这是需要设置10231事件忽略坏块,然后使用CTAS方式重建表最后rename table,然后再rebuild index
alter session SET EVENTS '10231 trace name context forever,level 10';
create table tab_new as select * from tab;
rename tab to tab_bak;
rename tab_new to new;
alter index indexname rebuild;
session中设置完时间后成功ctas,丢失了几千条数据,接受范围内。
select INDEX_NAME from user_indexes where table_name='xxxxx'; 发现没有索引,省下了重建索引的步骤。
然后别忘记关闭事件
alter session SET EVENTS '10231 trace name context off';
当时也猜测可能不止有一个坏块,就做了下全库校验。
rman>backup validate check logical database;
validate check logical database可以验证物理损坏和逻辑损坏,执行VALIDATE命令后通过查询V$DATABASE_BLOCK_CORRUPTION 视图可以获得坏块的详细信息
检验后查询视图
发现不止一个数据文件有问题
dbv file5 48个坏块
file#2是undo表空间,幸运的是其他的坏块上面都没有对象,新建一个UNDOTBS2看看
在使原undo下线的过程中发生错误
查询下活动的段
select sum(bytes) from dba_undo_extents where tablespace_name='UNDOTBS1' and status='ACTIVE';
select tablespace_name,segment_name,status from dba_rollback_segs;
等了半个多小时还是没有offline,重启了数据库成功切换过来。这里不知道有没有其他风险?
下面处理file#5 上面的坏块,由于没有数据,查询坏块位置在空闲段上面
Select * from dba_free_space where file_id= 5 and 568379 between block_id and block_id + blocks -1;
处理这样坏块的方法是查询下这个数据文件的剩余空间是多少,建一个表,把剩余区段分配给这个表,插入数据占用剩余空间,覆盖损坏的块。
查询剩余空间
数据文件的可用空间
SQL> select tablespace_name,file_id,sum(bytes/1024/1024) Mb from dba_free_space where file_id=5 group by tablespace_name,file_id;
新建张测试表
SQL> create table s (n number, c varchar2(4000)) nologging tablespace xxxx;
手动分配段
SQL> alter table s allocate extent (DATAFILE ‘D:xxxxxxx′ SIZE 剩余空间M);
向该表中插入100行数据:
BEGIN
FOR i IN 1..100 LOOP
INSERT INTO s VALUES(i,’x');
END LOOP;
END;
/
然后对其进行循环插入,直到前文中所述的坏块被使用。
BEGIN
FOR i IN 1..1000000000 LOOP
INSERT INTO s select * from s;
END LOOP;
END;
/
空间用完后,坏块被覆盖。
进入rman,重新校验数据库。
查询结果,很奇特
file#2 已经没有了,但是还提示有问题,这个视图不能删除记录,重启也没消失。
想到一个办法,新建一个表空间,它的数据文件为2,在校验数据库,由于是新建的一定没有问题,验证后发现此方法可行
查询v$database_block_corruption ,结果已经为空,此时删除qwe这个表空间,问题到此结束。
当然,数据库改成了归档模式。
归档模式下,rman>blockrecover corruption list; 在大量损坏时很方便。