某客户的一个表在进行分析和建索引一段时间时,均报ORA-8103错误。
让我们先看看ORA-8103错误是个什么样的错误?
[oracle@xty ~]$ oerr ora 8103
08103, 00000, "object no longer exists"
// *Cause: The object has been deleted by another user since the operation
// began, or a prior incomplete recovery restored the database to
// a point in time during the deletion of the object.
// *Action: Delete the object if this is the result of an incomplete
// recovery.
从上面的信息来看,引起这个错误的并不是由于什么对象被删除或者不完全恢复引起的。看来剩下的可能就是BUG或者是坏块了。
select /*+ parallel(a 6) no_index(a) */
count(lrrq) from hz2004.HJXX_RYZPXXB a
由于表很大,100g左右,因此等了好长一段时间,就报了ORA-8103错误。由于不同的SQL语句(建索引、分析表和查询表数据)都报了这个错误,基本可以确定是坏块引起的问题。
由于表中有long raw类型,因此不能通过从主键取得ROWID再根据ROWID读到值以后插入新表,由于查询表有问题,导出也不会成功。因此决定想办法来修复这个问题:
首先要确定是哪个块出现问题:
SQL> alter session set max_dump_file_size=unlimited;
SQL> alter session set db_file_multiblock_read_count=1;
SQL> alter session set events ‘immediate trace name trace_buffer_on level 1048576′;
SQL> alter session set events ‘10200 trace name context forever, level 1′;
SQL> select /*+ no_index(a */ count(*) from hz2004.hjxx_ryzpxxb a;
(注:经测试,在10g中,需要去掉trace_buffer_on那一个语句才会有trace,否则没有trace文件)
再次报错时,检查trace文件,发现如下的信息:
Consistent read started for block 11 : 09c63a9e
env: (scn: 0×0886.245ea878 xid: 0×0000.000.00000000
uba: 0×00000000.0000.00 statement num=0 parent xid:
xid: 0×0000.000.00000000
scn: 0×0000.00000000 0sch: scn: 0×0000.00000000)
从trace文件中可以发现在读文件号39块号408222时报错。
执行:
select * from hz2004.hjxx_ryzpxxb
where rowid=dbms_rowid.rowid_create(1,7415,39,408222,0);
报ORA-08103错误,可以确认是39号文件408222块坏。
然而用dbv命令检查39号文件,没有发现坏块。
通过dd取出39号文件408222块,发现该块居然是一个未格式化的块,但是该块在表的High water mark以下。单从该块来说是一个好的块,所以dbv检查并不会报坏块。
既然如此,我就故意做成一个坏块,然后让oracle跳过这个坏块。关闭库之后,用dd把坏块复制出来保存在一个文件,然后修改该块,使之成为一个坏块(很多的方法,这里我的方法就是修改其checksum值)。然后用dd复制回去。重启库之后,用 dbms_repair.skip_corrupt_blocks过程设置表在读取数据时,跳过坏块。
再次读取该表的所有数据,不再报错。
客户进行建索引和分析时也不再报错,顺利进行。
当然后续的工作,还是需要将数据导出来再导入,这样更稳妥。
我是一oracle初学者,前来参观,请多指教
[回复]
请教:
文件号39块号408222 怎么计算处理的。
[回复]
在那个trace文件里面有这么一句:
Consistent read started for block 11 : 09c63a9e
09c63a9e是正在读的块的RDBA,也就是rfile#=39,block#=40822
trace文件中读到这个块时,就中止了,说明这个块就是引起错误的块。
[回复]
明白了,谢谢!
[回复]
09c63a9e 换成二进制
0000 1001 1100 0110 0011 1010 1001 1110
前10位数rfile# 0000 1001 11 换成十进制为 39
后22位数block# 00 0110 0011 1010 1001 1110 换成十进制为 408222
[回复]
熊哥,我细化了你用dd改checksum值的过程,详细请见:
http://dbsnake.com/2009/02/ddchecksum.html
[回复]
ALTER SYSTEM SET EVENTS=’10231 trace name context forever,level 10′ 的效果应该和dbms_repair.skip_corrupt_blocks一样,可以跳过坏块。
[回复]
to qsxing:
是,那个事件也是要跳过坏块,但是你这样设置一个系统事件,如果一个其他的表出现坏块,不出现报错信息,就会埋下隐患啊。
[回复]
有可能会出现这样的情况,看来有些事件不能随便设置。我考虑问题还是不太全面 O(∩_∩)O
[回复]
熊哥,对于改checksum值,用BBED改也是可以的,详细请见:
http://dbsnake.com/2009/02/bbedchecksum.html
[回复]
to allantrey
谢谢。
不过当时用ultraedit故意改成的一个坏块。
[回复]
laoxiong
不错哦!
我也在成都(学生)!
成都也有位大师级的人物!
[回复]
[…] ORA-01410错误通常见于通过索引访问表,而索引或表由逻辑上的损坏。而这里显示没有通过索引访问表?那问题出在哪里呢?在这种情况下,这个错误与ORA-08103极其类似,参照《记一次ORA-8103错误的处理》: […]
跪求大哥qq指导,小弟现在数据库恢复后也遇到这个问题,qq30303073768,大哥能加一下吗 万分感谢
[回复]