前两天在某个客户现场发现ORA-08102报错:
ORA-08102 -- 未找到索引关键号,对象号:xxx, 文件号:xxx ,块号: xxx
之前我们刚刚给客户做过 xTTS的迁移,从11.2.0.4的AIX到11.2.0.4的Linux.
经检查,发现报错的索引在原库的状态为UNUSABLE, 但在迁移后的目标库中状态却变为USABLE,且segment大小明显不一样,目标库的SEGMENT大小小很多。
进一步检查表里的记录数和索引里的记录数,发现迁移后的索引中记录的行数目非常小。
--表内数据 select /*+FULL(A)*/ count(UPDATE) TABLE_CNT from SR.ST_XXX A; 1966217 --索引内数据 select /*+INDEX(A IDX_SI_UPDATE)*/ count(UPDATE) INDEX_CNT from SR.ST_XXX A ; 242
后来确认命中BUG 22869914 : UNUSABLE INDEX USABLE AFTER TTS CAUSING WRONG RESULTS(内容见附件)
由于bug, 索引的状态在TTS的过程中可能从UNUSABLE变为USABLE, 但由于之前状态为UNUSABLE, 所以Segment在原库中早就中断了更新,迁移后反而开始更新,于是索引里的记录和表记录不一致,最终导致ORA-08102。
请近期或者计划通过TTS(含xTTS)进行迁移的同事注意此BUG.
针对近期刚做过TTS迁移的:
1. 如果可以,检查原库及生产库中是否存在UNSABLE索引:
select owner,index_name,partition_name,subpartition_name from dba_ind_subpartitions where status ='UNUSABLE' union all select owner,index_name,partition_name,null from dba_ind_partitions where status ='UNUSABLE' union all select owner,index_name,null,null from dba_indexes where status ='UNUSABLE';
2. 如果在迁移过程中开启ENABLE_DDL_LOGGING参数,可以通过在目标库的alert log中搜索UNUSABLE关键字,结合时间点判断是否创建过UNUSABLE 索引
3. 如果有索引在原库中为UNUSABLE而在新库中为USABLE,建议客户沟通,删除或者重建该索引.
针对后续需要做TTS迁移的:
1. 确保原库中不存在UNSABLE索引,如果存在,请根据客户要求,删掉或者重建。
select index_owner,index_name,partition_name,subpartition_name from dba_ind_subpartitions where status ='UNUSABLE' union all select index_owner,index_name,partition_name,null from dba_ind_partitions where status ='UNUSABLE' union all select owner,index_name,null,null from dba_indexes where status ='UNUSABLE';
2. 其他对象,也尽可能不要在不是正常状态下进行迁移。
3. 建议TTS迁移过程中开启ENABLE_DDL_LOGGING参数。
4. 一定要确保迁移前后除Oracle内置数据库对象的一致性,比较里面必须包括STATUS。
以下为一个高效的两边数据比较的SQL, 除了DBA_OBJECTS, 也可以套用到其它对象的比较。
select OWNER,OBJECT_NAME,OBJECT_TYPE,STATUS,MAX(SITE) SITE FROM( SELECT OWNER,OBJECT_NAME,OBJECT_TYPE,STATUS,'LOCAL' as SITE from dba_OBJECTS local union all SELECT OWNER,OBJECT_NAME,OBJECT_TYPE,STATUS,'REMOTE' as SITE from dba_OBJECTS@remote remote ) group by OWNER,OBJECT_NAME,OBJECT_TYPE,STATUS HAVING COUNT(*)=1