love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

Phone:18180207355 提供专业Oracle/MySQL/PostgreSQL数据恢复、性能优化、迁移升级、紧急救援等服务

某金融客户Oracle 19c RAC logical corruption

本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

本文链接地址: 某金融客户Oracle 19c RAC logical corruption

这几天实在太忙,刚弄完文档。业务线的同事就找到我,说一个银行客户的核心系统昨晚出了故障,还没找到原因,希望能帮忙分析下。

从提供的信息来看是业务跑任务报错,遇到了Oracle-00600和ora-07445 错误。

这里完全不用去看这个600错误和7445错误是什么含义,从前文的日志来看,似乎在做一个block recovery出了异常。通过提供的alert 继续往前翻发现,在当天晚上22点过就开始报错了。

老实说这个报错其实很眼熟,但是用户google都搜不到这个错误。其实也搜了下mos发现根本搜不到。

但是从字面意思来看,kdsgrp1-qetlbrcb 和kdsgrp1 应该是差不多的含义和处理思路。

这里简单解释一下这个关键错误: ORA-00600: internal error code, arguments: [kdsgrp1-qetlbrcb], [7], [1712681731], [95], [], [], [], [], [], [], [], []

这表示读取数据时发现第7号表空间的第1712681731号block(这是10进制,需要转换成file/block)的第95行数据 读取报错。

既然如此我们就干脆来看看trace文件得了,更加直观一些。

实际上这里就描述的相对清晰了。 看到这里,我是多么希望国产数据库在这方面也能加强加强。

上面的信息我简单翻译一下就是,该业务SQL通过索引回表发现该表所在的408号文件的1405699号block的95行数据找不到。 那么这里可以根据trace来看看上面提到的索引block的dump,看看索引中的数据是否存在:

可见索引数据是存在的,且索引block的数据是完整的,但rows只有112条。

接下来我们继续看对应的数据块dump内容:

Oh my God!这个数据看起来是有问题的。首先看dump 该block显示有113行数据,似乎跟index的数据是不匹配的(索引只有112条);其次该block对应的第95行数据。。。这看起来完全是乱码呀。

先不说是不是真的乱码,首先这行数据的行指针指向了另外一个block 0xc10b0831的3133行数据。而且看上去这行数据显示该block时一个cluster table。

很明显,我们这个数据块所在的表是一个普通表,不是cluster table。最起码的,列都对不上呀。

实际上看该trace的上下文,发现这个数据块有3行数据都有问题。实际上这个数据块的结构是完整的,只是block的数据异常(包括row directory),因此这是一个逻辑坏块。

比如看该block的itl中比较新的一个事务对应的redo record记录,发现是有行迁移的(实际上看block dump也能看到)。

通过分析trace发现该数据块之前的redo dump记录都是正常的,而且只有update和insert操作,并无delete记录(看redo opcode即可)。

最终客户通过重建表暂时解决了问题。

那么问题来了,这个问题是怎么产生的呢?

老实说我比较怀疑写丢失导致的bug,毕竟redo都是正常的。

而看前面的dump我们可以看到:kdsgrp – dump CR block dba

这表示oracle报错的时候dump 内存块时,发现这个block是一个cr block。我们知道Oracle中的cr是利用 落盘后的数据块+undo 进行重构的。

难道说之前写数据落盘的时候,这个block就有问题了,所以后面构造的cr block也是有问题的。

这里我在测试环境验证一下这个问题。

破坏一下行头 是否可以恢复

可以看到,居然能恢复这个逻辑坏块。这个逻辑坏块可查,只不过有问题这行数据显示为乱码而已。

如果去dump数据块看,确实是乱码:

因为这里模拟构造了cr block,因此可以看到实际上有多个cr block,因为dump 该dba buffer会发现trace中有多行记录。

不过这不重要,我们发现多个dump 记录中的第三行数据都是乱码。

那么这说明什么问题,说明实际上默认情况下对于逻辑坏块在读取时并没有进行校验。

那么如果预防这样的问题,实际上oracle提供了一些方法,比如打开block和索引的读写校验,实际上就可以避免上面测试遇到的问题。

此时报错的信息,也会在alert log详细打印,明确告你是什么对象的什么block有问题。

写在最后。所以你认为B表的数据被写到了A表,你认为这是Oracle Bug吗。

想了解更多内容,可以参考这2个课程系列文章。

某金融客户Oracle 19c RAC  logical corruption插图(2)

Leave a Reply

You must be logged in to post a comment.