变更不重启,就是害自己!--技术人生系列第三十三期-我和数据中心的故事

来源:这里教程网 时间:2026-03-03 12:35:17 作者:

看到这个标题,相信不少朋友有类似的感慨:

是呀,变更(前)不重启,就是害自己!前人挖坑,后人踩

相信不少朋友有过类似残酷经历,做了一个变更,重启之后,出问题了

到底是本次变更导致还是以前留下的深坑呢 ?   查不清的只能默默地背锅了

y 的建议是:

 

         理想情况下,条件允许,做变更前,先重启一下,验证正常才开始变更。 但是,这也只是一个理想情况而已。

很多时候,我们可以做到系统上线前来一次重启操作系统,但是又有多少人可以做到变更前、变更后都重启一下呢?太难了,不是每个变更都有重启的机会的 .. 也是无奈啊!

今天小 y 和大家分享的就是这样一个,重启操作系统后出现数据库出现大量坏块的案例。

      问题  来了      

电话响了

前同事的同事,前ITPUB的资深版主,所在单位出了个比较大的故障。

Q: “小 y 救急, 数据库掉电重启后出现大量坏块, 数据库无法open, 没有备份 ,你帮看看呗…客户自己的判断是:掉电重启把system表空间1号数据文件的文件头写乱了,你可以参考下 ...”

 小y :  好的,你把他联系方式发给我吧!等我消息

这个世界真是奇妙,两个不认识的陌生人之间,中间居然只隔着三个熟人! 正在家里补觉的我,一听到有故障,顿时精神起来! 赶紧爬起床,洗了个脸,准备投入战斗; 加了 QQ, 对方发过来一张图片。

数据库在startup命令发出后,到了open阶段,报错如下

可以看到

数据库在open的过程中,发现1号文件/oracle/oradata/ora_system01.dbf出现了 datafile header ismedia corrupt ,即文件头介质损坏。看到这里,有同学想要猜一下原因:

是不是底层磁盘损坏无法访问了啊

 

答案是No!

如果是底层磁盘损坏无法访问 , 则会在 OS 层报 IO 相关的错误,这里没有,显然不是这个问题,退一步讲,即使是这个问题,但是当前在 没有rman和逻辑备份的情况下,接下来如果是你,怎么处理?

 

……

……

……

什么时候往下翻,由你决定…

……

……

……

……

……

……

        开启 分析   之旅      

1 查看alert日志

“出现文件头损坏, alert 日志会记录更详细的信息,你贴下 alert 日志的报错吧”

可以看到:

1)         System 表空间的 1 号数据文件 1 BLOCK ,报了坏块, Corrupt block, 原因是 Bad header

2)         重读数据文件头,依然是损坏

3)         对于该 block, 计算出来的 checksum ,因此基本可以排除掉 IO 丢失 (lost write) 导致的损坏。

 

接下来如果是你,不妨思考一下,你会怎么处理?

……

……

什么时候往下翻,由你决定…

……

……

……

……

……

……

……

……

……

2 第一次头脑风暴

对于该block,计算出来的checksum是0,因此基本可以排除掉IO丢失导致的损坏。 Oracle 发现该数据文件头损坏,原因是 bad header, 这时会将 block header 的内容打印出来,如下图所示

到底是哪里出了问题,导致 ORACLE 判断是 1 号文件 1 号块是 bad header 呢? 最简单的方式,我们把 header 的内容挨个对一下

1 这里 type=11 format=2 是典型的数据文件头的类型和格式,没有问题

2 rdba:0x00800001 rdba 记录了这个 BLOCK 的地址,即属于哪个文件哪个 BLOCK

是不是这里出了问题呢?(如果不是,则继续把 block header 的内容继续检查下去)

 

因此,小 y 首先检查一下 rdba:0x00800001, 看看 block 内记录的数据块地址是不是文件 1 BLOCK1。 方法很简单,将 0x00800001 转为 10 进制,再用 dbms_utility 转为文件号块号即可。

 

过程如下图所示:

这一转,坏块的问题就立刻显现了!

Open 数据库时,按照控制文件中记录的 1 号文件的名字,访问 1 BLOCK 的时候,解析 BLOCK 的格式,其中 4-7 字节存的数据块地址

翻译过来,却发现是 2 号文件 1 号块!而不是 1 号文件 1 号块!因此,数据库报了坏块!

3 科普一下--了解下数据块的格式

下图为一个数据库块的格式的简单示意图

其中,BLOCK的4到7字节(总计4个字节)是rdba,记录着这个数据块的地址,即属于哪个文件哪个BLOCK。在open数据库的过程中,Oracle开始读取

1 号文件 1 号块,

1 号文件 2 号块

但是当读到 1 号文件 1 号块后,校验块的格式时, 发现第 4 到第 7 个字节的 RDBA 其实是 2 号文件 1 号块! 因此,不可避免的报坏块,而数据库无法启动。

一句话概况为:

“我要的是 1 号文件 1 号块,但是你给我的块里的内容是 2 号文件 1 号块,!

所以是 bad header, 坏块!”

这是什么情况?

难道是掉电重启出现了卷管理 misplace 的问题?所谓 misplace, 就是上层应用(数据库)不关心底下的存储摆放,由卷管理帮忙维护和管理,但是如果 block 放错了位置,则可能出现这样“这里应该存放这个内容,但实际不是这个内容”的情况,也就是 misplace 的一种情况。

 

知道这个,又能如何呢?

接下来如果是你,不妨思考一下,你会怎么处理?

……

……

什么 时候往下翻,由你决定

……

……

……

……

……

……

……

……

……

4 接下来应该做什么?

也许接下来,有些同学开始支招了:

1、可否设置_ALLOW_RESETLOGS_CORRUPTION、_corrupted_rollback_segments、ORADEBUG推进SCN、10231跳过坏块等方式强行将库打开再导出重建呢?

 

答案是 NO !这里文件头坏块,这样的方式不可行。

 

2、可否bbed修改rdba地址和其他BLOCK的内容为正确的内容呢…

 

答案也是 NO !继续往下看,你就会明白为什么不可以。

 

这也不行,那也不行,那可怎么办是好!

 

正确的姿势应该是 :

1 )采用 DBV 校验下所有文件,确认有多少损坏

2 )判断损坏的原因

3 )然后接下来再采取对应的解决方案。

 

“你dbv校验过所有数据文件么?情况如何,坏的多么?”我问道。

“dbv结果显示,只有1号文件是坏块的,并且是大量损坏,报错和之前类似,都是bad headr所以我怀疑是卷管理把文件写乱了!”

 

无奈?知道有多少损坏又如何?还是无能为力? 如果是你,接下来你会怎么选择

5 客户的选择—最后的希望破灭了

在联系到小 y 之前,客户这边由于无法查到原因,数据库又无法打开,且无可用的备份; 时间紧急,所以客户已经使用 DUL 数据抽取软件对数据文件进行直接抽取了 ,不过不幸的是,遇到了下图的一堆错误; DUL 直接抽数的路也行不通后,这才多方联系到中亦

y, 这个错误到底是什么意思呢 ( 当小 y 看到这张图的时候,脸上浮现一丝诡异的笑 …)

 

这个错误很简单, wrong dba, 不是指错误的数据库管理员,而是错误的数据块地址 Data Block Address ,以最后一条记录为例

“当他抽取 file#1,block# 46502 2这个BLOCK的数据时,检查BLOCK内的rdba,发现翻译出来是file#2, block# 465022,是文件2,不是文件1”

因此是错误的数据块地址,故跳过不抽取。 这里不难看出,块号是一样的!只是文件号从 1 都变成了文件 2

6 不妨来一个大胆的猜想

看到这里,估计不少朋友,开始有点感觉了,想要一试身手。

是不是 1 号文件文件名没变,但是内容被 2 号文件覆盖了啊?

例如 cp 覆盖就有这样的效果!

 

说的没错!但是没有人会 cp ,这点从历史命令和沟通可以确认。

这个问题的本质就是:

ORACLE 认为 ora_system01.dbf 1 号文件(控制文件里记录),但是访问到该文件的时候,实际上文件里的内容都是 2 号文件的内容,这就是为什么块号全部一样,但是文件号全部从 1 变为 2 的原因了!

但是什么情况下出现的这个情况呢

实际上,当小 y 第一眼看到 DUL 的这个错误的时候,我就已经猜到了原因,尽管我从来没有遇到过这个问题,确切说,在 10 年前,喜欢思考的我,就猜到了未来我一定会遇到这个问题。只不过,我等这个问题,等了 10

如果是你,不妨思考一下,你会怎么处理?

……

……

什么时候往下翻,由你决 定…

……

……

……

……

……

……

……

……

……

……

7 真相大白,so easy!

1 首先,我们看看报错的 1 号文件

可以看到,名字上虽然是文件系统 , 但实际上是一个裸设备

2 检查裸设备和块设备的对应关系

可以看到,system表空间1号文件对应的裸设备,是对主设备号为253、次设备号为5的块设备进行绑定的。

3) 检查主设备号为253、次设备号为5的原始块设备信息

可以看到,真相出现了: 253:5,实际上对应的是ora_sysaux01.dbf,而不是我们所期望的system01.dbf 而sysaux01.dbf实际上是对应2号数据文件, 而不是1号文件

4) 检查1号文件对应的块设备信息

可以看到: Ora_system01.dbf对应的块设备是253:4

8 被误会的重启

Linux上,如果使用裸设备做为数据文件,则需要通过raw命令实现块设备到裸设备的绑定。 但是raw命令是当前生效,重启后会丢失,为了避免重启后裸设备绑定丢失,需要在规则文件中配置,在重启操作系统的时候,自动执行绑定到裸设备的命令

于是,我们检查了一下配置的规则文件,如下所示

不难看到,由于配置错误, 误将253:5绑定为/dev/raw/raw1,而raw1做了一个软连接到ora_system01.dbf,导致重启之后,ora_system01.dbf里存储的内容实际上都是2号文件sysaux这个LV的内容,因此数据库现了大量坏块

9 问题完美解决解决

没错,数据库实际上没有损坏,而只是单纯的对应关系错乱!

在将配置关系调整正确后,重启操作系统,数据库正常启动。 差不多1刻钟的时间,我们将问题完美解决了!

 

y, 这一单,没少赚吧 ”, 也许有同学关心这个

 

实际情况是,我们没有收取一分钱,朋友的朋友介绍,就是纯帮忙而已了! 不过后来当我出差到客户所在城市的时候,一起吃了顿饭,交了个朋友,还是很不错的…

 

      问题 原因   经验 总结      

故障原因总结

1)      上线前,一开始通过 raw 命令直接绑定的块设备和裸设备的对应关系是正确的。但是上线前没有重启过操作系统

2)    但是为了避免重启丢失,配置规则写错了 , 误将253:5(实际为2号文件 sysaux )绑定为/dev/raw/raw1,而raw1做了一个软连接到ora_system01.dbf,导致重启之后,ora_system01.dbf里存储的内容实际上都是2号文件sysaux这个LV的内容,因此数据库现了大量坏块!

3)      数据库实际上没有损坏,在修改配置关系正确后,问题圆满解决,无任何数据丢失,数据是一致的。

经验总结

1)      出现故障时,一定要冷静、冷静、再冷静!避免不正确的病急乱投医。在这个 case 中,即时客户采用 DUL 抽取数据成功,则抽取的数据也不能是保证一致的,设置隐含参数和 event 强行拉库的方式更是不可取;

2)      上线前务必重启操作系统,不要给未来埋雷,否则炸死的是他人还是自己,都不知道;

3)       技术虽然重要,但掌握原理才可以处理更为疑难的问题。掌握数据抽取软件 DUL 的使用,并不能解决这个问题,工具只是辅助手段而已;

4)       为什么小 y 可以在一刻钟内解决这个问题呢?这是学习和思考习惯的问题。小 y 10 年前安装 LINUX+ 裸设备时,就已经发现了这种配置方案本身存在的问题,例如根据磁盘分区绑定裸设备,但是当分区名字发生变化,不就错乱了么。这个 CASE 虽然有点不一样,但本质是一样的。这个问题,我等了十年,但是期间我时刻准备好了。我还在时刻准备着遇到我没有遇到过的问题。

通过这样一个案例,你不难发现,遇到问题,冷静是非常重要的。

而扎实的基础、细节把握以及冷静的现场能力,则可以让你在技术的道路上越走越顺!

相关推荐

热文推荐