Oracle ORA-01578坏块解决方法
本帖最后由 paulyi 于 2014-1-19 13:15 编辑
一. 出问题时的情景
我在自己测试数据库上给大表 tb_table导完数据后,建立索引时,出现以下错误
ORA-01578: ORACLE data block corrupted (file # 7, block # 28969)
ORA-01110: data file 7: 'D:\ORACLE\ORADATA\PAUL\GAME_LARGE.DBF'
查看alert.log日志时有以下错误
Corrupt block relative dba: 0x01c07129 (file 7, block 28969)
Bad check value found during buffer read
Data in bad block -
type: 6 format: 2 rdba: 0x01c07129
last change scn: 0x0000.00035361 seq: 0x1 flg: 0x04
consistency value in tail: 0x53610601
check value in block header: 0x302a, computed block checksum: 0x8
spare1: 0x0, spare2: 0x0, spare3: 0x0
二. 解决方法
1.执行以下语句看哪个段坏了
select segment_type,owner||'.'||segment_name
from dba_extents
where 7 = file_id and 28969 between block_id and block_id+blocks -1
segment_type owner.segment_name
TABLE PARTITION PAUL.TB_CASHFLOW_LOG
2.使用诊断事件
如果损失的是数据,ok
我们可以设置内部事件,使exp跳过这些损坏的block
SQL> ALTER SYSTEM SET EVENTS ‘10231 trace name context forever,level 10’;
取消内部事件设置
如果你在初始化参数中设置的,注视之
如果在命令行设置的
alter system set events='10231 trace name context off';
3、创建一个临时表tb_cashflow_log_tmp的表中除坏块的数据都检索出来
SQL>CREATE TABLE tb_cashflow_log_tmp as select * from tb_cashflow_log;
4、 更名原表
SQL>alter table tb_cashflow_log rename to tb_cashflow_log _bak;
SQL>alter table tb_cashflow_log _tmp to tb_cashflow_log;
5、在tb_cashflow_log上重新创建索引、约束、授权、trigger等对象
6、 利用表之间的业务关系,把坏块中的数据补足。
然后用DBV来检验坏块:
E:\Oracle\oradata\paul>dbv file=block.dbf blocksize=8192
1. exp正常吗, 将exp的数据imp到一个临时表中, 看看数据的记录数是否正确啊.
2. 如果正常, 直接删除目前的数据表, 在利用测试数据重建这个表就好了.
3. 如果不正常. 使用10231的trace event, 再使用create table as select 重建对应的表之后, rename当前表, 再将对应的数据块, dump出来, 自己构建相应的数据内容吧.
三、事后分析产生这种问题的原因
1、 十之八九这个Oracle的数据库server打开了异步I/O(async io)或增加了写进程。
2、 硬件的I/O出现了错误。
3、 操作系统的I/O或缓存出现我问题,比如操作系统对于异步I/O的补丁没有打。
4、 手动的修改了数据文件中的数据,我模拟这个错误用的便是这种方式。
四、如何尽量减少问题及问题的损失呢
分析了产生问题的原因,我认为可以采取以下几个措施
1、 在为提高性能为操作系统打开异步I/O时,一定要与oracle及操作系统与异步I/O相关的补丁要打全。
2、 制定一个良好的备份恢复策略,最好有表的exp备份
3、 要及时的检查硬件的状态,及时更换驱动器部件
这次测试数据库又出现系统表空间有坏块,目前情况下只能通过重建库来解决了,重新导入备份的数据
要是索引块坏的话还是比较好处理,重建索引即可
所以最好保证不出问题,要有良好的备份.