一
27
在一个表上建索引时,报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错误。
如果这个库不是查询库,也就是表不能truncate,该如何呢?
[回复]
老熊 回复:
1月 29th, 2010 at 9:57 上午
@jlttt, 不是查询库的话,也得找个合适的时间重建这个表了(逻辑坏块不太容易用备份恢复回来)。重建时绕过那个坏块即可,比如通过已有的索引根据ROWID插入数据。
[回复]
老熊 回复:
1月 29th, 2010 at 11:01 上午
@jlttt, 不过,即使是生产库,可以仔细检查一下内存中的数据与磁盘上的数据是否一致,如果不一致,刷新一下buffer cache也许就好了。
[回复]
可不可以尝试用 analyze table validate structure cascade
[回复]
楼上哥们,analyze只是检查吧,如何修复呢?
[回复]
学习!
[回复]
给熊哥拜个早年哈,祝虎年大吉!
[回复]