在一个表上建索引时,报ORA-01410错误,我们查询这个表来重现这个错误:

Connected to:
Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
With the Partitioning option
JServer Release 9.2.0.6.0 - Production

SQL> set timing on
SQL> set time on
14:20:03 SQL> select /*+ full(a) no_index(a) */ count(*) from crm.cust_order a; 
select /*+ full(a) no_index(a) */ count(*) from crm.cust_order a
                                                    *
ERROR at line 1:
ORA-01410: invalid ROWID

ORA-01410错误通常见于通过索引访问表,而索引或表由逻辑上的损坏。而这里显示没有通过索引访问表?那问题出在哪里呢?在这种情况下,这个错误与ORA-08103极其类似,参照《记一次ORA-8103错误的处理》

14:27:00 SQL> alter session set max_dump_file_size=unlimited;

Session altered.

Elapsed: 00:00:00.01
14:27:18 SQL> alter session set db_file_multiblock_read_count=1;

Session altered.

Elapsed: 00:00:00.00
14:27:18 SQL> alter session set events 'immediate trace name trace_buffer_on level 1048576';

Session altered.

Elapsed: 00:00:00.00
14:27:18 SQL> alter session set events '10200 trace name context forever, level 1';

Session altered.

Elapsed: 00:00:00.00
14:27:18 SQL> select /*+ full(a) no_index(a) */ count(*) from crm.cust_order a; 
ERROR at line 1:
ORA-01410: invalid ROWID


Elapsed: 00:05:50.82
14:33:09 SQL> 14:33:09 SQL> alter session set events 'immediate trace name trace_buffer_off';

Session altered.

在trace文件的最后,我们可以看到:

Consistent read started for block 10 : 2489c394
  env: (scn: 0x0a0d.690ff414  xid: 0x0000.000.00000000  uba: 0x00000000.0000.00  statement num=0  parent xid: xid: 0x0000.000.000000
00  scn: 0x0000.00000000 0sch: scn: 0x0000.00000000)

这里只有"start“,而没有finish,表明在读2489c394这个块出了问题。
用ODU工具的rdba查看文件号和坏号:

ODU> rdba 2489c394

  rdba   : 0x2489c394=613008276
  rfile# : 146
  block# : 639892

通过"alter sytem dump datafile 146 block 639892”命令发现块中的object_id与CUST_ORDER表的data object id不同,看起来这就是问题所在(此处不再列出数据)。
看起来有坏块了。不过这个库是个查询库,把表TRUNCATE之后重新从生产库同步过来,发现问题仍然存在,甚至把表DROP之后重建也是如此,均是发生在146/639892这个块上。

而TRUNCATE/DROP表都不能解决问题,显然这个块还在内存中,看起来需要刷新buffer cache了:

14:37:07 SQL> alter session set events 'immediate trace name flush_cache level 1';
Session altered.

刷新buffer cache后,问题解决。

总结:这个问题,与ORA-8103类似,都是出现了逻辑坏块,只不过这次的坏块是发生在内存中的块。至于坏块是怎么进入到内存中,为什么在重建表后还在内存中,这就是个谜了,或者是ORACLE的BUG,或者跟用的同步软件DSG有关。在这个案例中,块的object_id与段的实际的data object id不一致。而object_id不一致有时也会报ORA-600错误。

此时此刻,我迎来了2010年的第一个加班。在这么一个杯具性时刻,还是要祝所有的朋友们,新年快乐!

回顾2009年,用一句简单的话来说就是,“这一年没有白过”。

看看这一年,有些什么样的收获:

自己开发的ODU软件,走向成熟,得到了许多朋友的认可,也帮助很多朋友解决了燃眉之急。从年初发布v2.0.1版,到支持压缩表,中间相隔了3个月的时间。从那之后,就是一些功能的完善和BUG的修复,到如今已经相对比较稳定。通过开发这个软件,我自己对ORACLE的块格式有了相当清楚地了解,同时这个软件也发挥了他独特的作用,帮助一些朋友恢复了数据。

与盖国强、杨廷锟、段林仲、邹德平合作的《Oracle DBA手记》,即将面世。这完全是一个意外。通过这样的写作,收获是巨大的。我也希望除BLOG之外方式的知识分享,能够让更多的从事Oracle数据库相关工作的朋友受益。

技术方面,理论知识方面进展不大,但是实战经验值大幅提升。学习,从来都是实践与理论相结合。新的一年,争取有更进一步的突破。

作了房奴,收了房,也有了代步的工具。压力是越来越大了。争取明年七八月时能住进新房。

这一年,也是辛苦的一年。特别是最近2个月,加班与通宵已经成为十分常见的活动,无奈的是,绝大多数时候没办法控制这样的事情的发生。

2010年,我希望也有更多的收获:

  • 争取把OCM给过了。谁叫这玩意儿商业需求是如此的旺盛。
  • 多写一些有价值的技术文章。
  • 接触接触Oracle之外的东西。