接到开发人员和业务人员的通知说一个登陆页面不能用了报错 :: [mondaoOamUserDAO] :select错误 javasqlSQLException: ORA state 这个错误是由于索引失效造成的重建索引后问题就解决了 为了搞清楚索引为什么会失效以及如何解决我们做个测试 首先我们创建一个普通的测试表(非分区表) SQL> create table t(a number); Table created SQL> select tablespace_name from user_segments where segment_name=T; TABLESPACE_NAME
DATA_DYNAMIC SQL> 然后我们创建一个普通索引 SQL> create index idxt on t(a); Index created SQL> insert into t values(); row created SQL> set linesize SQL> select index_nameindex_typetablespace_nametable_typestatus from user_indexes where index_name=IDXT; INDEX_NAME INDEX_TYPE TABLESPACE_NAME TABLE_TYPE STATUS IDXT NORMAL DATA_DYNAMIC TABLE VALID SQL> 模拟索引是失效的情况 SQL> alter table t move tablespace tools / Table altered SQL> select index_nameindex_typetablespace_nametable_typestatus from user_indexes where index_name=IDXT; INDEX_NAME INDEX_TYPE TABLESPACE_NAME TABLE_TYPE STATUS IDXT NORMAL DATA_DYNAMIC TABLE UNUSABLE SQL> 我们看到当使用类似 alter table xxxxxx move tablespace xxxxxxx 命令后索引就会失效 当然作为测试也可以直接使用alter index idxt unusable;命令使索引失效例如 SQL> alter index idxt unusable; Index altered SQL> 在这种情况下我们向表中插入数据看看是什么情况 SQL> insert into t values(); insert into t values() * ERROR at line : ORA: index MISCIDXT or partition of such index is in unusable state SQL> 我们看到这时就出现了常见的ORA: index XXXXXXXX or partition of such index is in unusable state错误 检查一下索引状态我们会注意到索引已经是UNUSABLE了 SQL> select index_nameindex_typetablespace_nametable_typestatus from user_indexes where index_name=IDXT; INDEX_NAME INDEX_TYPE TABLESPACE_NAME TABLE_TYPE STATUS IDXT NORMAL DATA_DYNAMIC TABLE UNUSABLE SQL> 对于普通表中的不同索引(非唯一索引)我们有两种方法解决这个问题 方法一设置 skip_unusable_indexes=true; SQL> alter session set skip_unusable_indexes=true; Session altered SQL> insert into t values(); row created SQL> commit; Commit complete SQL> select * from t; A
rows selected SQL> select index_nameindex_typetablespace_nametable_typestatus from user_indexes where index_name=IDXT; INDEX_NAME INDEX_TYPE TABLESPACE_NAME TABLE_TYPE STATUS IDXT NORMAL DATA_DYNAMIC TABLE UNUSABLE SQL> 现在我们看到这个索引的状态虽然还是UNUSABLE但是通过设置alter session set skip_unusable_indexes=true; 我们已经可以访问这个表了但是请注意这种情况下这个索引是不可用的也就是说优化器在考虑是否要使用索引时是不考虑这个所以的 方法通过常见所以彻底解决这个问题 首先先设置 skip_unusable_indexes=false也就是不跳过失效索引 SQL> alter session set skip_unusable_indexes=false; Session altered SQL> 然后重建这个失效的索引 SQL> alter index idxt rebuild; Index altered SQL> select index_nameindex_typetablespace_nametable_typestatus from user_indexes where index_name=IDXT; INDEX_NAME INDEX_TYPE TABLESPACE_NAME TABLE_TYPE STATUS IDXT NORMAL DATA_DYNAMIC TABLE VALID SQL> 我们看到重建索引后索引的状态就正常了 现在插入数据看看是正常 SQL> insert into t values(); row created SQL> commit; Commit complete SQL> 看来重建索引才是解决这类问题的彻底的方法 |