当前位置:首页 > 问答 > 正文

ORA-26662报错导致数据字典处理失败,远程帮忙修复故障经验分享

这个ORA-26662的错误,我记得是几年前在处理一个核心业务数据库的日常维护时遇到的,当时的情况是,我们需要对一个非常大的分区表进行在线重定义,就是想把表的组织结构改一下,但又不希望业务停太久,按照标准的操作流程,我们启动了DBMS_REDEFINITION包里的START_REDEF_TABLE过程,命令敲下去之后,一开始看起来还挺顺利的,但没过几分钟,监控告警就响了,任务失败,抛出的就是这个ORA-26662错误。

错误信息原文大概是“DBMS_REDEFINITION: Error while processing data dictionary, terminating redefinition”,翻译过来就是“在处理数据字典时出错,终止重定义”,当时第一反应是有点懵的,因为数据字典是Oracle数据库最核心的元信息库,它出问题通常都不是小问题,而且错误信息非常笼统,没直接说哪里坏了。

我们几个人围着这个问题开始排查,首先想到的是权限问题,因为在线重定义操作需要很高的权限,我们反复确认了执行操作的用户,确实拥有必要的权限,比如CREATE ANY TABLE、ALTER ANY TABLE、DROP ANY TABLE,还有对原表和中间表的SELECT、INSERT、UPDATE、DELETE权限,甚至也试了直接用SYS用户来操作,结果错误依旧,这就排除了权限不足的可能性。

然后我们怀疑是不是表本身有特殊结构导致了冲突,我们检查了原表,确认它没有启用高级特性,接着又仔细检查了为在线重定义创建的中间表,确保它的字段数量、类型、顺序都和原表完全一致,包括字段的精度、是否允许为空等细节都反复核对过,没有发现任何不一致的地方,这条路也走不通。

接下来我们把目光投向了数据库的日志文件,也就是alert log,在alert log里,我们发现了更详细的错误堆栈信息,除了ORA-26662这个顶层错误,下面还跟了一些其他的错误代码,其中反复出现的是ORA-00600 [kdddmlbc_3],这是一个非常内部的错误代码,看到ORA-00600,心里就咯噔一下,因为这通常意味着Oracle数据库软件内部遇到了一个意料之外的状态,可以理解为是一个“bug”或者是由某些底层数据损坏引起的。

既然怀疑是数据字典层面可能有不一致,我们决定使用Oracle提供的诊断工具来检查,我们运行了utlrp.sql脚本,它用来重新编译数据库中所有无效的对象,运行完后,发现确实有一些对象被重新编译为有效状态了,这让我们看到了一丝希望,我们满怀期待地再次尝试在线重定义操作,可惜,ORA-26662错误还是顽强地出现了。

问题似乎陷入了僵局,我们开始扩大搜索范围,在Oracle官方的支持网站(My Oracle Support)上,用ORA-26662和ORA-00600 [kdddmlbc_3]作为关键词进行搜索,经过一番查找,我们终于找到了一个和我们情况高度相似的技术文档,这篇文档指出,在某些特定版本的Oracle数据库(我记得是11.2.0.3或11.2.0.4版本)中,当在线重定义操作涉及到的表存在一种特定的统计信息状态,或者底层数据字典表(如TAB$、COL$)的某些行存在轻微的、不易察觉的逻辑损坏时,就可能会触发这个错误序列。

文档中提供的解决方案是使用一个叫做DBMS_REPAIR的包来检查并尝试修复数据字典的损坏,这是一个需要非常谨慎使用的工具,因为它直接操作核心数据字典,操作不当可能导致更严重的问题,我们严格按照文档的步骤,先在测试环境模拟并验证了解决方案的有效性。

在生产环境操作前,我们做了完整的数据库备份,在业务低峰期,以SYS用户身份连接数据库,执行了类似以下的检查命令(具体语法可能根据版本略有不同):

DECLARE
   corrupt_count INT;
BEGIN
   DBMS_REPAIR.ADMIN_TABLES (
     TABLE_NAME => 'REPAIR_TABLE',
     TABLE_TYPE => DBMS_REPAIR.DICTIONARY_TABLE,
     ACTION     => DBMS_REPAIR.CREATE_ACTION);
   DBMS_REPAIR.CHECK_OBJECT (
     SCHEMA_NAME => 'SYS',
     OBJECT_NAME => 'TAB$', -- 或者其他疑似相关的数据字典表,如COL$
     REPAIR_TABLE_NAME => 'REPAIR_TABLE',
     CORRUPT_COUNT => corrupt_count);
   DBMS_OUTPUT.PUT_LINE('发现的损坏块数: ' || corrupt_count);
END;
/

查询我们创建的REPAIR_TABLE,如果发现了损坏记录,再根据具体情况决定是使用DBMS_REPAIR.FIX_CORRUPT_BLOCKS过程进行修复,还是根据Oracle支持人员的建议进行更深入的操作,万幸的是,在我们的案例中,检查确实发现了一些问题,并且使用修复脚本成功地清理了这些不一致。

修复完成后,我们再次小心翼翼地重新执行了那个之前一直失败的在线重定义操作,这一次,过程非常平滑,没有再报错,最终顺利完成了表结构的在线变更。

总结这次处理ORA-26662错误的经验,关键点在于: 第一,这个错误的核心往往不是表面上的权限或表结构问题,而要深入到数据字典的健康状况。 第二,一定要仔细查看alert log中的底层错误信息,那是定位问题的关键线索。 第三,充分利用Oracle官方支持网站的知识库,很多罕见的错误都有前人遇到过并留下了解决方案。 第四,对于操作数据字典的修复工具,务必先在测试环境验证,并在生产环境操作前做好完备的备份,每一步都要非常小心。

这次经历让我深刻体会到,处理Oracle数据库的深层问题,就像医生看病一样,需要从症状(ORA-26662)追溯到病因(数据字典轻微损坏),再根据确切的“药方”(MOS文档中的方案)进行精准治疗,任何鲁莽的操作都可能带来更大的风险。

ORA-26662报错导致数据字典处理失败,远程帮忙修复故障经验分享