深入解析:由expdp遇到ORA-7445问题的深入展开

李真旭(Roger)

ACOUG 核心专家,Oracle ACE,云和恩墨技术专家

编辑手记:由一个问题入手,深入其根本原因,层层递进,细致分析,由点及面,这是DBA进阶的捷径之一。

某客户说一套数据库由于非正常关机重启之后,进行数据导出发现报错,expdp 无法正常工作,报错之后直接退出:

而检查此时的 alert log 可以发现有如下类似的错误:

从上面的信息我们可以得到如下几个结论:

1、expdp 的写进程报错,因为日志产生是 dw 进程。

2、dw进程报错的原因是遭遇了 ora-07445 [klufprd()+321] 错误。

3、对于 [klufprd()+321] 这个函数,非常少见,但是从前面2点我们可以知道这肯定与 buffer cache 有关系。

所以要临时解决这个问题也很简单。通过 alter system flush buffer_cache 刷新缓存之后,再次进行 expdp 操作。

后续客户尝试了之后,发现 expdp 操作虽然仍然会报错,但是 expdp 不会异常终止,会继续完成后面其他对象的导出。

进一步分析报错的信息可以看到,有如下这样的提示:

很明显,这里提到这个这个表,恰好就是 expdp 报错所遇到的表,只不过我们刷新 buffer cache 之后,expdp 可以跳过这个表继续完成其他对象的导出。

从上述的信息来看,这里存在错误。客户也意识到,通过 dbv 对数据文件进行检查,但是发现文件并没有损坏。

这里我们要注意,dbv 同时是检查物理坏块,对于逻辑坏块通常无能为力,当然块内的逻辑错误,这类型的块 dbv 是可以检查出来的。

但是从这里的信息来看,Oracle 发现所需要的这行记录 row 01808438.0 应该在 file 6 block 33784 中找到,但是却并没有发现。

注意,这里的 file 6 block 33784 本身是完好的。

那么这里的 row 01808438.0 表示什么含义呢? 其实这是表示的 nrid;这可以理解为一直指针;其中前面一部分是表现 rdba 地址,后面表现行编号。

如果要进一步分析为什么会这个错误,我们怎么办呢? 很简单,分别将 block 33784以及rdba 01808438(16进制) 进行 dump。 如下是转换的脚本:

日志报错中提到的是 row 01808438.0 ,那么我们首先来分析 file 6 block 33848的dump:

上述类似表示的是 rdba 地址 01808438 的第0行,也就是我们大家所理解的第一行。我们可以发现这行记录中,行头存在一个nrid地址。

说到 nrid 地址,这通常是针对行链接,行迁移才会遇到的一种情况。那么这里为什么会出现呢?

行迁移几种,最常见的一种其实是 block 内的。一个 block 中单条记录的最大列数是255列,当一行记录的列超过255时,其他的列数据库会被 oracle 分成另外一个 row piece 存在同一个 block 中(当然也有可能存到其他 block)。

也就是说超过255列的行数据,会被分成多个 row piece;而当我们读取这个行数据时,怎么知道是一个完整的整体呢?

答案就是 nrid,oracle 通过 nrid 来将这多个 row piece 串在一起,组成一个完整的行数据。

想到这一点,那么我们再回头去看下前面的错误。row 01808438.0 表示这个 block 的第0行,而该 block 的第0行所存在的 nrid 地址是:0x018083f8.e

那么我们进一步到 block 0x018083f8 中去寻找第e行记录,发现结果是这样的:

上述类似表示的是 rdba 地址01808438的第0行,也就是我们大家所理解的第一行。我们可以发现这行记录中,行头存在一个 nrid 地址。

说到 nrid 地址,这通常是针对行链接,行迁移才会遇到的一种情况。那么这里为什么会出现呢?

行迁移几种,最常见的一种其实是 block 内的。一个 block 中单条记录的最大列数是255列,当一行记录的列超过255时,其他的列数据库会被oracle 分成另外一个 row piece 存在同一个 block 中(当然也有可能存到其他 block)。

也就是说超过255列的行数据,会被分成多个 row piece;而当我们读取这个行数据时,怎么知道是一个完整的整体呢?

答案就是 nrid,oracle 通过nrid来将这多个 row piece 串在一起,组成一个完整的行数据。

想到这一点,那么我们再回头去看下前面的错误。row 01808438.0 表示这个 block 的第0行,而该 block 的第0行所存在的 nrid 地址是:0x018083f8.e

那么我们进一步到 block 0x018083f8 中去寻找第e行记录,发现结果是这样的:

我们可以看到这里对应的记录根本就没有。因为该 block 最后一条记录是 row 13,也就是第14行,也是一个 row piece,而且存在一个 nrid.

该 nrid 是 0x018083f8.c,这表示该 block 33784 第12行记录。跟 row 13 是组合成一条完整行记录的。

换句话说,我们前面报错的那条记录,应该有2个 row piece,其中一个 row piece 是存在的,其中一个 row piece 本应该存在在 33784 block 中。

但是由于找不到该 row piece,因此 oracle 报了上述的错误。

实际上该错误遇到之后,我们通常以为是 index 的问题,通过 drop 重建可以解决,然而这里的问题比较特殊,据说是表的数据有问题。

所以这就是为什么客户重建 index 会报错的原因:

最后,我们清楚了所有原因,那么要解决该问题很简单。通过 rowid 的方式跳过这行有问题的记录,将其他数据取出,重建表即可。

原文发布于微信公众号 - 数据和云(OraNews)

原文发表时间:2016-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

P4和POF的对比

一、简介 软件定义网络(SDN)技术的发展已经历了多年,新技术层出不穷。OpenFlow作为其中的一个代表性协议,已经进化了多个版本,并被工业界和学术界广泛接受...

3713
来自专栏CSDN技术头条

REST API URI的七大设计原则

在了解REST API URI设计的规则之前,让我们快速浏览一些我们将要讨论的术语。 URIs REST API使用统一资源标识符(URI)来寻址资源。在当今互...

1986
来自专栏unlike

用paxos实现多副本日志系统--multi paxos部分

上篇 basic paxos : https://cloud.tencent.com/developer/article/1147420

1737
来自专栏皮振伟的专栏

[database][redis]redis技术分析

前言: 解读一下redis的源代码~ 因为hash算法,skiplist等相关文章很多,前人之述备矣,这里不做解读。这里会解读一些相对较“冷门”的代码。 分...

34410
来自专栏IT技术精选文摘

GO语言版鹅厂广告交易实时平台价格解析

腾讯广告实时交易平台在向竞价胜出一方返回成交价的时候,先对价格进行TEA加密,再对密文进行BASE64编码,接收方先对BASE64解码,再对密文解密,双方事先...

633
来自专栏java思维导图

2018 年,去百度面试 Java 后端的一次面试经历

来自:风铃无声江舟听雨 链接:https://www.jianshu.com/p/e8bb9bfb3253 一、百度一面 1、给一个函数,返回 0 和 1,概率...

2824
来自专栏Jerry的SAP技术分享

Netweaver工作进程的内存限制 VS CloudFoundry应用的内存限制

一个会话进程能够在堆上申请的内存大小上限, 在事务码RZ11里查看参数abap/heap_area_dia:

1824
来自专栏杨建荣的学习笔记

关于分区表的move操作(r2笔记90天)

关于分区表的move操作还是很值得深究的一个问题。如果分区表中含有lob字段,难度还会加大。 对于普通的表而言,做move操作室理所当然,oracle提供的方...

3145
来自专栏乐沙弥的世界

MongoDB执行计划获取(db.collection.explain())

803
来自专栏Crossin的编程教室

【每日一坑 6】 查找文件内容

Hello 大家好,我终于又来挖坑了。 上次的坑好像反响不是很好,论坛上只有两份解答。其实这题难度不大,不用什么特殊的函数来解决,就是字符串、队列的各种操作,可...

2497

扫描关注云+社区