深入解析:由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 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

5756
来自专栏张善友的专栏

Silverlight + Model-View-ViewModel (MVVM)

     早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expr...

3038
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2636
来自专栏Golang语言社区

【Golang语言社区】GO1.9 map并发安全测试

var m sync.Map //全局 func maintest() { // 第一个 YongHuomap := make(map[st...

4918
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2675
来自专栏魂祭心

原 canvas绘制clock

4314
来自专栏杨龙飞前端

scrollto 到指定位置

2564
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.3K7
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3265
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

32810

扫码关注云+社区