日期:2014-05-16  浏览次数:20445 次

表扫描与索引扫描返回的行数不一致

某个应用最近总出现死锁,其中一些是因为报了索引和数据行存在不匹配的问题,MOS中有如下文档可以参考。


ORA-1499. Table/Index row count mismatch(文档 ID 563070.1)
现象
使用“validate structure cascade”分析表时报ORA-1499的错误,trace文件中包含“Table/Index row count mismatch”的错误信息。例如:
SQL> analyze table test validate structure cascade;
analyze table test validate structure cascade
*
ERROR at line 1:
ORA-01499: table/index cross reference failure - see trace file 


trace文件中包含:
Table/Index row count mismatch 
table 6559 : index 10000, 0 
Index root = tsn: 6 rdba: 0x01400091
意味着扫描表返回6559行数据,索引扫描返回10000行数据。“Index root”是索引的段头信息。rdba: 0x01400091是相对于数据块地址的索引段头。他是十进制的20971665,Rfile#=5,Block#=145。

SQL> select dbms_utility.data_block_address_file(20971665)  "Rfile#"  ,dbms_utility.data_block_address_block(20971665) "Block#"  from dual;   
Rfile#     Block#   
---------- ----------   
5          145


运行下面的查询明确关联的索引:

SQL> select owner, segment_name, segment_type  from  dba_segments  where header_file = 5  and header_block = 145;  

OWNER    SEGMENT_NAME    SEGMENT_TYPE 
-------- --------------- ------------------ 
SCOTT    I_TEST          INDEX 
这种逻辑不一致性也能通过10g以上版本的ORA-600 [kdsgrp1]错误或低版本的ORA-600 [12700]错误来说明。

原因
这是一种表与索引之间的逻辑不一致。这种逻辑不一致通常是因为表上的高水位(HWM)出现了问题,全表扫描比索引扫描返回了更少的行。这种不一致性也可能是由于Oracle的defect或会引起IO丢失的OS/硬件问题导致的。

解决方案
可以通过下面的语句查询出全表扫描时未扫出的索引行:
select /*+ INDEX_FFS(<tablename> <indexname identified in 2.1>) */ rowid 
      , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
      , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
from <tablename> 
where <indexed column> is not null 
minus 
select /*+ FULL(<tablename>)*/ rowid 
     , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
     , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
from <tablename>; 

实例:
select /*+ INDEX_FFS(TEST I_TEST) */ rowid 
      , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
      , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
from test 
where