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

简介: 某个应用最近总出现死锁,其中一些是因为报了索引和数据行存在不匹配的问题,MOS中有如下文档可以参考。ORA-1499. Table/Index row count mismatch(文档 ID 563070.1)现象:使用“validate structure cascade”分析表时报ORA-1499的错误,trace文件中包含“Table/Index row count mismatch”的错误信息。

某个应用最近总出现死锁,其中一些是因为报了索引和数据行存在不匹配的问题,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 c2 is not null 
minus 
select /*+ FULL(TEST)*/ rowid 
      , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
      , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
from test; 

使用下面PLSQ中的索引,可以将全表扫描丢失的行存储到另一张表中:

drop table test_copy; 

create table test_copy as select * from test where 1=2; 

declare 
  cursor missing_rows is 
        select /*+ INDEX_FFS(TEST I_TEST) */ rowid rid 
        from test  
        where c2 is not null 
        minus 
        select /*+ FULL(TEST)*/ rowid rid  
        from test; 
begin 
  for i in missing_rows loop 
      insert into TEST_COPY 
          select /*+ ROWID(TEST) */ * from TEST where rowid = i.rid;  
  end loop; 
end; 
/

- 当索引返回的比表记录少时,重建索引可以解决这个问题。
- 当索引返回的比表记录多时,重建索引或执行虚拟insert插入该表的操作以提高HWM,可以最终解决这种逻辑错误。在以上这个案例中,修复了逻辑错误,但这些行也还是可能丢失了,因为是在执行这里提到的方法之前运行了上述PLSQL脚本。

如果从Oracle Support需要额外的帮助,请提供:
1. analyze语句分析的trace文件。

2. 第一个查询语句的结果。

3. dump基表段头产生的trace文件。
select header_file, header_block, tablespace_name from   dba_segments 
where  owner = upper('&table_owner') and segment_name = upper('&table_name');

alter system dump datafile &header_file block &header_block;

trace文件用来明确HWM。
@ Example from a block dump not using ASSM (Automatic Segment Space Management):  
@  
@ Extent Control Header  
@ -----------------------------------------------------------------  
@ Extent Header:: spare1: 0 spare2: 0 #extents: 4 #blocks: 31  
@ last map 0x00000000 #maps: 0 offset: 4128  
@ Highwater:: 0x014000d6 ext#: 3 blk#: 5 ext size: 8  
@  
@ So, HWM is located at RDBA 0x014000d6 in extent_id=5 and block#=5 in that extent. 

4. 这个查询结果可以明确索引多返回的行的区id:
select rid, a.relative_fno, a.block, e.owner, e.segment_name, e.segment_type, e.extent_id, e.blocks 
from (select /*+ INDEX_FFS(<table name> <index name>) */ rowid rid 
            , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
            , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
      from <table owner.table name> 
      where <indexed column> is not null 
      minus 
      select /*+ FULL(<table name>)*/ rowid rid 
            , dbms_rowid.ROWID_RELATIVE_FNO(rowid) relative_fno 
            , dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block 
      from <table owner.table name> 
     ) a 
    , dba_extents e 
where a.relative_fno=e.relative_fno 
and e.tablespace_name = upper('&tablespace_name') 
and v.ts#=&tablespace_number 
and (a.block between e.block_id and e.block_id+blocks-1); 

注意:
- 以上SQL中请替换owner、表名、索引名和索引列。
- 表空间是上述步骤3提供的。
- 这个SQL查询提供了索引返回行位置的区extent。

目录
相关文章
|
分布式数据库 Hbase
HBase StochasticLoadBalancer组件介绍
HBase StochasticLoadBalancer组件介绍。
3084 0
|
Shell Linux Ubuntu
解决在SecurecCRT登录后,发现方向键、backspace(退格键)、delete(删除键)为乱码的问题
问题:使用securecrt ssh到linux之后,backspace(退格键),delete(删除键),以及4个方向键都为乱码,不能正常使用。按tab键也没有自动补全文件名。 即: 按Backspace(退格键)和delete(删除键)屏幕显示的是:^H 按方向键则屏幕显示的是:^[[A^[[B^[[C^[[D 环境: SecureCRT8.
4264 0
|
12月前
|
JSON API 开发者
解密小红书详情API接口:获取与运用
小红书作为热门社交媒体平台,吸引了大量用户和创作者。企业或开发者可以通过调用小红书API接口,高效、合法地获取内容数据,提升业务效率。本文详细介绍如何获取和使用小红书笔记详情API接口,涵盖注册账号、创建应用、获取API密钥、查阅文档、构建请求、解析响应等步骤,以及应用场景和注意事项。
3210 2
|
弹性计算 供应链 并行计算
阿里云ECS包年包月、按量付费、抢占式实例、节省计划和预留实例券付费类型详细说明
阿里云服务器计费多样化:包年包月适合长期服务,预付费且划算;按量付费适合短期项目,后付费、按小时结算;抢占式实例享折扣但可能被释放,适合无状态任务;预留实例券抵扣按量付费账单;节省计划提供承诺使用量的折扣,适用于资源用量稳定或周期性变化的业务。
505 0
|
Java 网络架构 Spring
SpringMVC之@RequestMapping详解
【1月更文挑战第19天】 一、@RequestMapping注解的功能 二、@RequestMapping注解的位置 三、@RequestMapping注解的value属性 四、@RequestMapping注解的method属性 五、@RequestMapping注解的params属性 六、@RequestMapping注解的headers属性 七、SpringMVC支持ant风格的路径 八、SpringMVC支持路径中的占位符(重点)
386 2
|
SQL 关系型数据库 MySQL
Navicat使用HTTP通道连接MySQL(远程mysql3306端口关闭或者只允许localhost链接状态)...
Navicat使用HTTP通道连接MySQL(远程mysql3306端口关闭或者只允许localhost链接状态)...
6516 0
Navicat使用HTTP通道连接MySQL(远程mysql3306端口关闭或者只允许localhost链接状态)...
|
前端开发 JavaScript Java
毕业设计|Springboot+vue 学生心理咨询评估系统
毕业设计|Springboot+vue 学生心理咨询评估系统
234 1
|
SQL OceanBase
obdumper` 工具
obdumper` 工具
677 1
|
安全 NoSQL Java
[网络安全]shiro安全框架基本原理及架构功能简析
[网络安全]shiro安全框架基本原理及架构功能简析
321 0
|
SQL 存储 Oracle
Oracle之3种表连接方式(排序合并连接、嵌套循环、哈希连接)
Oracle之3种表连接方式(排序合并连接、嵌套循环、哈希连接) 排序合并连接 1.2.4.2.1  排序合并连接 排序合并连接(Sort Merge Join)是一种两个表在做表连接时用排序操作(Sort)和合并操作(Merge)来得到连接结果集的表连接方法。
3649 0