项目场景
在某项目数据库运维群,有现场同事发了张报错截图如下。
报错复现很简单:
现场有一张重要性很高的业务表,因为隐私,我在这里给它赋名为A表。现场对A表做INSERT、UPDATE、DELETE等操作时,全部报错,报错提示就是上面的ORA-00600。
也就是说现在在A表上发生任何事务,都会报错ORA-00600。
问题分析
ORA-00600是Oracle数据库内部错误。这个错误通常会伴随一个错误代码(例如:ORA-00600: internal error code, arguments: [1234], [a], [b], [c], ...)。上图即是例子。它没有一个具体的解决方案。可以登陆 my oracle support 查询比对。
但对于实际生产来讲,等不及问题分析查清解决了。所以采取了如下思路:
Ⅰ:将A表重命名为 A_BAK_0422
alter table A rename to A_BAK_0422;
Ⅱ:建一张空表,表名为 A
考虑到 A 表本身数据量庞大,有125G,所以不适合使用如下代码,效率太低。
CREATE TABLE A AS SELECT * FROM A_BAK_0422
所以只能建空表 A, 获取原来的建表语句,直接建表。
Ⅲ:创建新A表索引
获取旧A表的索引信息,给新A表也创建对应的索引。
此时新的A表上发生事务是没有问题的,业务此时其实已经可以恢复正常了。
Ⅳ:与旧表进行数据整合
现在新A表虽然已正常,业务也可以正常展开。但是A表毕竟还是缺失原有的数据,需要将旧A表的数据进行整合。此时整合的方式就有很多选择,可以写PLSQL,也可以使用kettle这种ETL工具都可以快速的进行整合。
Ⅴ:数据验证
整合完数据后,还是需要应用系统的工程人员进行数据验证,看是否正常。
优化建议
其实当时我有想过立即切换到容灾库,但是被领导否决了。因为该错误属于是逻辑错误,而项目上的RPO接近0,数据在实时进行同步,在发现报错时,逻辑错误数据已经同步到容灾备库中,即使切换到容灾备库,错误记录依然存在,数据库依然无法正常对外提供服务。需要手动处理掉数据库中的逻辑错误,才能修复数据库。
后来和处理该问题的前辈请教沟通,前辈讲的优化建议非常有用:
对容灾数据库定时做快照,在发生逻辑错误时,可以将容灾数据库回退到逻辑错误发生前,然后切换容灾数据库。