在插入数据时突然报错,ORA-01502: 索引 ‘USER.SYS_C0067978’ 或这类索引的分区处于不可用状态
奇怪,索引失效按说只是影响查询速度,索引失效怎末会导致无法插入呢
故障处理及问题排查
- 首先查看下索引状态
select index_name,index_type,table_owner,table_name,status from user_indexes where index_name='SYS_C0067978' and table_owner='GWM_FLS';
INDEX_NAME INDEX_TYPE TABLE_OWNER TABLE_NAME STATUS
SYS_C0067978 NORMAL UNUSABLE PF_REQUEST_LOG_CONTENT UNUSABLE
- 重构索引
alter index gwm_fls.SYS_C0067978 rebuild online;
推荐加online,使用online会在后台运行虽然速度慢一些不过不会锁表影响业务
- 原因回顾
错误原因:
回想前天对该库中的表排查行迁移,对该表进行了move在线重定义,move操作会导致rowid变化,所以会导致索引失效
继续下面聊一下为什么索引失效导致insert、update操作失效👇
索引为什么会导致insert、update失效
一般情况下,CBO不考虑使用UNUSABLE状态的索引,包含分区表。相关参数为SKIP_UNUSABLE_INDEXES,其作用如下所示:
SKIP_UNUSABLE_INDEXES作用:在DML期间跳过对索引的维护,这样可以提高DML的效率,可以事后一次性重建,但是SKIP_UNUSABLE_INDEXES=y对unique index不起作用,因为此时的unique index扮演者constraint的作用所以在insert数据时index必须被更新。
当参数SKIP_UNUSABLE_INDEXES设置为true时(默认),当数据库遇到不可用索引时,只会忽略而不会提示任何错误信息;同时即使该表上带有不可用的索引或索引分区,也可以针对该表执行DML操作,针对不可用索引对应的DML语句都将正常执行,而且数据库停止维护相关索引。
在进行DML(INSERT和UPDATE)操作时,如果是唯一索引,那么无论该参数的值设置为何值,Oracle都会去校验索引的可用性。如果索引不可用,那么就会报错ORA-01502。
当参数SKIP_UNUSABLE_INDEXES设置为false时,DML操作及CBO生成执行计划时都会考虑该索引。所有与UNUSABLE索引相关的操作都会失败,报错信息为:ORA-01502: 索引 '‘USER.SYS_C0067978’ 或这类索引的分区处于不可用状态。
move的注意事项
在对表进行move前要注意,move操作时如果不指定表空间,则在原表空间移动数据块,在这个表空间中需要至少额外一倍该表大小的空间。
数据重组后,其 rowid 发生了改变。index是通过 rowid 来 fetch 数据行的,所以表上的 index 需要 rebuild。
索引失效原因
库中索引状态已经是不可用的状态,回想导致索引的情况有哪些呢?
当某些操作导致数据行的ROWID改变,索引就会完全失效。可以分普通表和分区表来讨论哪些操作将导致索引失效。
普通表索引失效的情形如下所示:
① 手动置索引无效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。
② 如果对表进行MOVE操作(包含移动表空间和压缩操作)或在线重定义表后,那么该表上所有的索引状态会变为UNUSABLE。MOVE操作的SQL语句为:ALTER TABLE TT MOVE;。
③ SQL*Loader加载数据。
分区表索引失效的情形如下所示:
① 对分区表的某个含有数据的分区执行了TRUNCATE、DROP操作可以导致该分区表的全局索引失效,而分区索引依然有效,如果操作的分区没有数据,那么不会影响索引的状态。需要注意的是,对分区表的ADD操作对分区索引和全局索引没有影响。
② 执行EXCHANGE操作后,全局索引和分区索引都无条件地会被置为UNUSABLE(无论分区是否含有数据)。但是,若包含INCLUDING INDEXES子句(缺省情况下为EXCLUDING INDEXES),则全局索引会失效,而分区索引依然有效。
③ 如果执行SPLIT的目标分区含有数据,那么在执行SPLIT操作后,全局索引和分区索引都会被被置为UNUSABLE。如果执行SPLIT的目标分区没有数据,那么不会影响索引的状态。
④ 对分区表执行MOVE操作后,全局索引和分区索引都会被置于无效状态。
⑤ 手动置其无效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。
对于分区表而言,除了ADD操作之外,TRUNCATE、DROP、EXCHANGE和SPLIT操作均会导致全局索引失效,但是可以加上UPDATE GLOBAL INDEXES子句让全局索引不失效。
重建分区索引的命令为:ALTER INDEX IDX_RANG_LHR REBUILD PARTITION P1;。




