love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

Phone:18180207355 提供专业Oracle/MySQL/PostgreSQL数据恢复、性能优化、迁移升级、紧急救援等服务

Archivelog 模式下,datafile header损坏,如何恢复?

前几天一朋友的客户数据库出现故障,现象的有2个datafile的文件头彻底损坏,有可能是硬件问题导致。
当时由于是windows环境,通过远程桌面操作,太卡,加上接手之前已经有人经过一系列的操作,导致恢复
相对麻烦,我采取的方式是利用他们之前create 的datafile,借助bbed修改ckpt信息,然后将库先open后。
最后再借助数据抽取软件将备份的损坏datafile数据抽取出来,然后直接加载到数据库中。

这里我来使用vm模拟下如果仅仅是datafile header block损坏的情况下,如何去手工恢复?当然,如果还有
其他block损坏,比如datafile header前面的bitmap block,那么恢复就相当复杂了。

—先模拟文件头损坏的情况

此时启动数据库,你会遇到类似如下错误:

当然我这里模拟有点绝对了,部分情况下,这种情况下是可以recover的。如果说文件头block彻底损坏完了。是不能直接进行修复的。
如果你有备份,那么你可以从备份里面将该datafile restore 出来,然后再去进行recover,这样是的。

上次遇到的情况下,在我接手之前,已经有人重建过datafile,且重建过controlfile(原始文件没有备份).

类似的操作:alter database create datafile ‘/home/ora10g/oradata/roger/roger01.dbf’. 当然,这个步骤也需要你先
重建controlfile或者使用较旧的controlfile来替换当前的controlfile,不然你会遇到这样的错误:

针对这种情况下,创建datafile后,其scn是非常老的,如果你需要进行recover,那么需要从该scn开始至今的所有archivelog。

在这样的情况下起手就可以手工去修复数据文件头,如果是损坏很严重,那么你可以偷懒,从其他datfile copy过去,然后再修改。

+++++++++++ 如下是整个修复的过程,我这里来简单演示一下。

这里有个关键性的问题是,我们需要修改哪些地方? 这就需要你对datafile header的结构相对熟悉了。 dbsanke很早之前写过一篇,大家可以参考下。

++++++ 第一修改的地方:rdba_kcbh

这里是0x0100001,表示file 4 block 1,我们要将其改成正确的值:file 2 block 1 。 后面block号不变,即应该是0x00800001

++++++ 第2个修改的地方:kccfhfsz 即文件大小

首先你可以从os上去查看数据文件的实际大小,如下:
[ora10g@killdb roger]$ ls -ltr roger01.dbf
-rw-r—– 1 ora10g oinstall 10493952 Jan 28 06:31 roger01.dbf

不过需要注意一点的是,dbfile的大小应该你操作系统上看到的实际大小减去一个db block_size,因为还存在一个os block header。

++++++ 第3个修改的地方:kccfhfno datafile文件号

++++++ 第4个修改的地方:kscnbas v$datafile.create_change#

++++++++ 第5个修改的地方:kcvfhcrt 表示v$datafile.create_time

++++++++ 第6个修改的地方:kcvfhtsn 表示表空间号v$datafile.ts#

++++++++ 第7个修改的地方: kcvfhrfn v$datafile.rfile# 即相对文件号

+++++++++ 第8个修改的地方:kcvfhtnm 表空间名称即v$tablespace.name

这里补充一下,如果你的表空间名称跟实际不符,可能还需要修改kcvfhtln,表示长度。我这里是ROGER即为5.

最后我们来尝试下:

看来还有地方不对,我们来查询下v$datafile看下信息:

可以看到检查点信息不一致,这是因为开始我为了演示模拟中途open过了一次。

而目前datafile 2的实际scn跟实际不符:

我们可以看到,checkpoint scn和time都不对,所以还需要修改下:

修改完成之后我们可以通过dbv来检查下,看看文件头修改是否都正确,如下:

最后我们再来将数据库open,如下:

遇到过程了,先不要着急,我们来看下这个错误是什么意思? 从字面上的含义来看,意思是说改datafile的信息
可能比controlfile中的部分信息还要新,这个有可能,因为最开始我offline 文件后,open过,然后接着修改
文件头的时候的信息又是参考其他datafile header block来的,所以file 2的信息可能比以前的信息要新。

既然如此,那么我们重建下controlfile即可,注意要用noresetlogs方式创建:

从上面的提示来看,正常了,至少能够正常认到datafile 2了,提示需要进行介质恢复。

到这里就结束了,我认为本身这个没有任何难度,可能只是要理解文件头的结构以及了解相关的信息的含义,最后来个
简单的小总结,针对文件头损坏的情况下,在恢复的情况下可能需要修复如下内容:

1. rdba_kcbh (offset 4)即使文件头block的rdba地址
2. kccfhfsz (offset 44) 即文件大小
3. kccfhfno (offset 52) 即datafile文件号
4. kscnbas (offset 100) 即v$datafile.create_change#
5. kcvfhcrt (offset 108) 即v$datafile.create_time
6. kcvfhtsn (offset 332) 即v$datafile.ts#,表示表空间号
7. kcvfhrfn (offset 368) 即v$datafile.rfile#, 表示相对文件号
8. kcvfhtnm (offset 338) 即v$tablespace.name,表示表空间名称(根据实际情况,可能还会需要修改kcvfhtln,表示表空间名称字符长度)
9. kscnbas (offset 484) 即checkpoint scn
10.kcvcptim (offset 492) 即last checkpoint time.

当然,这个总结并不全面,可能很多情况还需要修改一些其他的地方,另外如果是system datafile,那么也会有所不同,比如oracle
数据库中的bootstrap$对象是存储在file 1 block 337中.而system 表空间的第一个datafile header中会有个root rdba地址是指向
bootstrap地址的,在11gR2版本中该地址变为file 1 block 521(不同版本可能有所差异).

2 Responses to “Archivelog 模式下,datafile header损坏,如何恢复?”

  1. Miaoyu_8 Says:
  2. 用bbed修改数据文件头,跳过丢失的归档 . | 学习oracle数据库 Says:

    […] 本文链接地址: Archivelog 模式下,datafile header损坏,如何恢复? […]

Leave a Reply

You must be logged in to post a comment.