ORA-01410 invalid rowid


    最近业务短信经常报出如下异常:

    系统错误编码:ORA-01410:无效的ROWID,错误源:PKG_BASE_DATA_XXXX,本地错误信息:TABLE_NAME=T_XXXX_CONN_MAC,错误位置:1-6.


     结合业务场景,经分析,是索引失效导致的big query无法检索到正确的数据。表数据是通过sqlldr使用direct方式加载到表中。下面主要分析一下这个异常。

Oracle Error: ORA-01410
Error Description:Invalid ROWID
Error Cause:
A ROWID was entered incorrectly. ROWIDs must be entered as formatted hexadecimal strings using only numbers and the characters A through F.

A typical ROWID format is '000001F8.0001.0006'.
A relatively frequent cause of the error comes from the habit of using automatic programs to rebuild multiple indexes.
For example, if you rebuild an index, Oracle will copy the index contents from one location to another and when the copy is complete, it will free up the space that held the original index contents. If there is a long running query that started before the rebuild the query will carry on running using the old index. If some other process now demands the space and puts something into it (perhaps by creating or extending a table or index), if the long-running query hits the old index it may suddenly find itself looking at a block that contains the wrong type of data for the wrong object id. When this happens an ORA-01410 error is produced.



     在使用sqlldr direct导入数据到表中,oracle需要自动的rebuild  index.但是在rebuild index的过程中,需要进行index的重新生成,这样如果在过程中之前的旧索引数据被读取之后,根据旧索引读取到的数据块肯定数据类型与数据对象ID都是错的,就会产生ORA-01410错误。

解决思路:避免索引失效,出现失效索引需要及时的修复索引。



在此引用此位博主总结的文章,写的比较全也比较好。


链接:http://blog.csdn.net/kechengtan/article/details/6191084


转载的内容如下:

一、问题发现

2月16日现场同事发现某个tablespace空间快要耗尽,让我们手工清楚些数据,腾出足够空间,等用户有预算添加磁盘。该问题年前已经处理过一次,我们已经将数据保留期限做了缩减,按道理不会这么快出现磁盘空间耗尽的情况。我猜测可能是自动分区程序没有运行,没有自动删除旧分区,而新数据又不断产生,导致磁盘空间被逐渐耗尽。


看出从2011-02-02开始到16号这段时间分区维护没有执行,导致空间满。
于是通知集成组同事运行自动分区维护程序。
自动分区维护运行后,空间使用率低于80%了。问题解决了。
过了1小时,现场同事又反映采集程序卡住不动了,让我们赶紧核查原因,排除故障,给出故障报告。
二、问题分析
首先想到的是不是哪个表被锁住了。
select * from v$locked_object t1,user_objects t2
where t1.object_id=t2.object_id
通过语句查到,确实有很多相关表被锁住了。
继续查是哪些语句锁住了表
select sid,
       v$session.username 用户名,
       last_call_et 持续时间,
       status 状态,
       LOCKWAIT 等待锁,
       machine 用户电脑名,
       logon_time 开始登入时间,
       sql_text
from v$session, v$process, v$sqlarea
where paddr = addr
   and sql_hash_value = hash_value 
   and status = 'ACTIVE'
   and v$session.username is not null
order by last_call_et desc;

发现有个delete语句在执行,该delete语句为:
delete from table1 where column1=? and column2=? and column3=?
看该语句的执行计划,发现是全表扫描,没有走索引。

我们估计是不是索引失效了
select status,T.* from user_indexes T
where table_name='TABLE1'
发现status='INVALID'失效。
重建该索引:
drop index ......
create index ......
问题解决。
是什么问题导致的索引失效呢?该问题是运行分区维护后发生的,于是把该问题转给了开发自动分区管理的同事了。该问题后续再补充。
三、知识点总结
1.如何判断和确认索引失效?
通过查看user_indexes的status来确定用户索引状态。
分区索引查看DBA_IND_PARTITIONS的status来确定。
2.重建索引的方式有哪些,有什么区别?
1)drop index...和create index
2)alter index idx_name rebuild
3)alter index idx_name rebuild online
a)rebuild会阻塞对基表的DML操作,但不会影响rebuild期间查询对原有索引的使用。
b)rebuild的数据源可能是基表,也可能是原索引。取决于基表和原索引的大小,那个小,rebuild时就会用那个作为数据源。
c)rebuild online运行用户在索引重建期间执行DML操作。
d)rebuild online的数据源是基表。
3.导致索引失效的原因有哪些?原因:当某些操作导致数据的rowid改变,索引就会完全失效。
那什么时候会导致rowid改变使得索引unuseable或者invalid呢?
一般普通表在在如下3个情况下可以使index unusable
1)move 【alter table move】【alter table t02 move tablespace tbs01;】
2)sqlldr 【sqlldr ( parallel or direct )append 】【sqlldr direct=y + 主键重复】
3)手动alter index unusable
对分区表,又要分local index和globa index来说
1)首先上面的导致普通表上的索引失效的原因对分区表也同样适用.
2)对local index在exchange without including indexes的时候也会unusable
3)global index在partition mt的时候会导致unusable[除非加上update global indexes]
以下为引用:
1.导致的原因: 
     在SQL*LOADER 加载过程中会维护索引,由于数据量比较大,在SQL*LOADER 加载过程中出现异常情况,导致ORACLE 来不及维护索引,导致索引处于失效状态,影响查询和加载。 异常情况主要有:在加载过程中杀掉SQL*LOADER 进程,重启,表空间不够等。
2.  global索引,当global 索引所在表执行alter table 涉及下列操作时,会导至该索引失效:

? ADD PARTITION | SUBPARTITION

? COALESCE PARTITION | SUBPARTITION

? DROP PARTITION | SUBPARTITION

? EXCHANGE PARTITION | SUBPARTITION

? MERGE PARTITION | SUBPARTITION

? MOVE PARTITION | SUBPARTITION

? SPLIT PARTITION | SUBPARTITION

? TRUNCATE PARTITION | SUBPARTITION

因此,建议用户在执行上述操作sql 语句后附加update indexes 子句,oracle 即会自动维护全局索引。

3. 执行alter table 时未指定update indexes 子句:

如果是range/list 分区,其local 索引和global 索引不会受影响;

如果是hash 分区,新加分区及有数据移动的分区的local 索引和glocal 索引会被置为unuseable,

需要重新编译

对于分区表中索引失效要重建索引

select 'alter index '||t.index_name||' rebuild partition '||t.partition_name from user_ind_partitions t where t.index_name='IDX_PART2'  and t.status='unusable'

查出来后,在命令窗口执行。查出来的语句就可以了。

你可能感兴趣的:(Oracle)