ITPub博客

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

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

Oracle 作者:记录每一次错误 时间:2018-12-03 14:35:46 0 删除 编辑

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

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



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

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



小 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 虽然有点不一样,但本质是一样的。这个问题,我等了十年,但是期间我时刻准备好了。我还在时刻准备着遇到我没有遇到过的问题。


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

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



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31547066/viewspace-2222496/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
性格开朗,有较强的学习能力,对oracle数据库的体系结构,搭建RAC,timesten,goldengate,分布式数据库,dataguard,系统调优有较深入的了解, 尤其是oracle优化,深入学习的主机命令,对数据库的优化,SQL语句的优化有深入的认识,目前正在shell脚本,mysql,以后会有计划学习大数据和python。

注册时间:2018-07-23

  • 博文量
    200
  • 访问量
    475104