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

相关文章

来自专栏机器之心

初学机器学习的你,是否掌握了这样的Linux技巧?

选自alexpetralia 机器之心编译 Linux 因其稳定性获得了不少开发者的青睐,同时也成为大多数服务器的操作系统,对于机器学习开发者来说,使用 Mac...

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

系统负载能力浅析

一. 衡量指标 用什么来衡量一个系统的负载能力呢?有一个概念叫做每秒请求数(Requests per second),指的是每秒能够成功处理请求的数目。比如说...

23850
来自专栏应用案例

主题建设之主题表

亿信BI中的分析表大多数都是基于主题表而创建的。那什么是主题?什么是主题表?主题表分哪几种类型、何种场景下使用、又是如何创建的?不同类型的主题表有什么区别等等,...

26980
来自专栏腾讯移动品质中心TMQ的专栏

30分钟轻松搞定代码瘦身

导语 当一个新的产品想要复用一个旧的产品的逻辑的时候,是直接把全盘的代码copy过去就可以了吗?站在功能的角度当然没问题,但是这对于新产品是相当臃肿的,因为一些...

26590
来自专栏SeanCheney的专栏

《Python分布式计算》 第7章 测试和调试分布式应用 (Distributed Computing with Python)概述常见错误——时钟和时间常见错误——软件环境常见问题——许可和环境常见

无论大小的分布式应用,测试和调试的难度都非常大。因为是分布在网络中的,各台机器可能十分不同,地理位置也可能不同。 进一步的,使用的电脑可能有不同的用户账户、不同...

27450
来自专栏云瓣

[译] 所有你需要知道的关于完全理解 Node.js 事件循环及其度量

原文地址:All you need to know to really understand the Node.js Event Loop and its Me...

304110
来自专栏极客猴

爬虫与反爬虫的博弈

近来这两三个月,我陆续将自己学到的爬虫技术分享出来。以标准网络库 urllib 的用法起笔,接着介绍各种内容提供工具,再到后续的 scrapy 爬虫框架系列。我...

24520
来自专栏架构师之路

细聊分布式ID生成方法

一、需求缘起 几乎所有的业务系统,都有生成一个记录标识的需求,例如: (1)消息标识:message-id (2)订单标识:order-id (3)帖子标识:t...

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

大分区表的手工并行优化

这段时间饱受大分区表的性能之苦,碰到最大的一个分区表有1个t左右,操作起来每个细节都需要格外小心,我这次和大家分享的案例应用的分区表不是很大,有80G左右。但是...

30640
来自专栏Python中文社区

一键获取免费真实的匿名代理

專 欄 ❈夏洛之枫,从销售转为程序员,Python爬虫爱好者。 github: https://github.com/ShichaoMa/proxy_fact...

27260

扫码关注云+社区

领取腾讯云代金券