看到这个标题,相信不少朋友有类似的感慨:
是呀,变更(前)不重启,就是害自己!前人挖坑,后人踩
!
相信不少朋友有过类似残酷经历,做了一个变更,重启之后,出问题了 !
到底是本次变更导致还是以前留下的深坑呢
?
查不清的只能默默地背锅了
…
小 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
虽然有点不一样,但本质是一样的。这个问题,我等了十年,但是期间我时刻准备好了。我还在时刻准备着遇到我没有遇到过的问题。
通过这样一个案例,你不难发现,遇到问题,冷静是非常重要的。
而扎实的基础、细节把握以及冷静的现场能力,则可以让你在技术的道路上越走越顺!
