暂无图片
暂无图片
5
暂无图片
暂无图片
暂无图片

oracle异常恢复(二)dul和bbed的使用

取名浪费我半小时 2020-11-10
1776


       在进入正文之前,我们先回忆一下上一期文章开头抛出来的三个问题:


  • 如果在生产环境中truncate了一张表,还能恢复吗?如果可以该如何恢复?

  • 如果在生产环境中offline了一个数据文件,等想再次online的时候,发现介质恢复所需要的redo log已经被覆盖了,还能恢复吗? 如果可以该如何恢复?

  • 如果在生产环境中误删了一个业务用户,还能恢复吗? 如果可以该如何恢复?


      对于第一个问题,我们已经知道了该如何去处理,今天我们来看第二个问题,并尝试在自己的测试环境中模拟并使用bbed工具解决这个问题。

      

       和上一篇一样,这里默认数据库是没有备份的也未开启归档模式。




      很多时候客户总是有很多理由要将一个数据文件offline,但是一段时间后出于各种原因又想将这个数据文件online,然后开始online,发现需要介质恢复,没关系那就recover呗,紧接着就悲催了,出于各种原因归档已经被删除了,redo log也在早八百年前就被覆盖了。这时候客户急了,这里面的数据很重要,不能丢啊,然后他就找到了你,你呢正在看这篇文章,看完后你一口答应,并觉得这就是一个小case。


       正式开始操作之前,我们先思考一个问题,为什么我们将数据文件offline之后再online的时候,需要介质恢复呢?很简单,因为在将数据文件offline的时候,oracle是不会帮你把内存中的脏块给刷下去的,一旦数据文件被offline,那么文件头的scn势必就静止了,不会再发生变化,但是我的数据库还有很多其他的数据文件,他们仍然在正常工作,并且时不时的还要将文件头的scn和控制文件中的scn进行同步 ,所以当你想把这个被offline的数据文件再次online的时候,oracle发现不对啊别人的scn比你大十万八千里,你这个数据文件什么情况,你自己先把自己的scn给搞对了再来找我(提示你需要recover),然后当你执行recover的时候,发现redo log已经被覆盖了,相关的归档日志也已经被删除了,这时候该怎么办呢?

  

       从上面的一段话中我们似乎已经知道了将数据文件online起来的前提是文件头的scn要和控制文件中记录的scn保持一致。那么我们偷偷私下一想,现在正常途径想一样是不可能的了,那我能不能去骗oracle呢?我把文件头的scn改成和其他数据文件的scn保持一致不就行了,你oracle又不知道。答案是肯定的,bbed这款工具就可以做这么一件事,下面我们开始测试。




  •     环境以及测试数据准备 

       

     

create tablespace tbs0801 datafile '/u01/app/oracle/oradata/ces/tbs0801.dbf' size 10M autoextend off;


create user test0801 identified by test0801 default tablespace tbs0801;


grant dba to test0801;


conn test0801/test0801


create table tb0801 as select * from dba_objects where rownum<101;



startup force mount;

alter database noarchivelog; 

alter database open;

 

select file#,to_char(checkpoint_change#),name,status from v$datafile;



       接下来我们将刚刚创建的表空间对应的数据文件12 offline,并且多切几次日志,模拟出一会online recover的时候没有相关的redo log(未开归档)而无法online的场景。


alter database datafile 12 offline drop;

select * from v$log;

alter system switch logfile;

alter system switch logfile;

alter system switch logfile;

alter system switch logfile;

alter system switch logfile;

alter system switch logfile;


       接下来我们开始online该数据文件


alter database datafile 12 online;

recover datafile 12;



      现在我们发现这个数据文件无法recover从而无法被online了,并提示我们缺少437号redo log,而所需的redo log也已经被覆盖了。


      我们再次查看数据文件及scn的信息


select file#,to_char(checkpoint_change#),name,status from v$datafile;


      我们发现被offline的数据文件的scn小于其他数据文件的scn,从理论上来讲,我们现在只需要将12号文件,文件头中的scn从3651324改为3651735即可。


      这里为了测试方便我们将库切到mount状态(实际上只要保证恢复过程中没有做checkpoint,就不需要停库的),这样一会操作的时候就不会受到ckpt进程的干扰了,这里需要注意的一点是,停库是会做checkpoint的,所以起到mount状态后,我们再查一次,结果如下:



       现在数据库处于mount状态,所以scn不会再发生变化。




      接下来我们开始使用bbed工具修改文件头的scn,初次使用bbed是需要编译的,编译命令如下,另外还需要一些依赖的包,这个大家自行下载上传到相应的路径即可。


--三个依赖的包及其对应的路径

$ORACLE_HOME/rdbms/lib/ssbbded.o

$ORACLE_HOME/rdbms/lib/sbbdpt.o

$ORACLE_HOME/rdbms/mesg/bbedus.msb


cd $ORACLE_HOME/rdbms/lib


--编译bbed

make -f $ORACLE_HOME/rdbms/lib/ins_rdbms.mk BBED=$ORACLE_HOME/bin/bbed


      在进入bbed之前我们还需要配置两个参数文件,par.bbed和par.list,内容如下:



      par.list的内容可以通过如下命令查出:


select file#||chr(9)||name||chr(9)||bytes from v$datafile;



      然后将查出的内容复制进par.list即可:



  • 进入bbed

cd $ORACLE_HOME/rdbms/lib


bbed  parfile=par.bbed



下面列出bbed常用的一些命令:


info、set、 find、 dump、 modify 、sum apply    examine、map 、print、 verify


       我们使用info命令可以看到par.list的内容(即可以看到我们接下来要操作的数据文件):



       前面我们已经说清楚了,现在只需要将12号文件文件头的scn改为和11号文件的scn一致就可以达到骗过oracle的目的,从而实现将12号数据文件online。那么现在问题来了,怎么才能知道文件头中的scn是存在哪个位置的呢?


       为了回答上一个问题,我们来看下11号文件的1号block(文件头),然后使用map命令将其结构打出来,从下图我们可以看出包含两个大的结构,kcvfh以及tailchk。



      我们再进一步的去查看kcvfh这个结构,使用p命令:


BBED>p kcvfh



       我们发现大的结构里面又套了很多小的结构,从名字上来看,kcvfhckp这个结构下面有个结构是kcvcpscn,似乎就是这一个,现在我们再往里深入:



       现在我们差不多可以确认kcvcpscn这个结构就是存的scn,他基于8K的偏移量为484,但是你有没有好奇为什么这个结构下面两个 kscnbas和kscnwap,对应偏移量分别是484和488,这个其实也很好理解,随着scn的不断增长,当scn的大小达到42亿时(4字节存储的上限),488偏移量对应的那个的值就会变为1,关于这一点理解就行,这里就不多说了。


       知道了scn存在的位置,现在就好办了,我们进入到偏移量为484的位置然后把里面的内容dump出来看看:



       很简单就能推出c1ba3700存的就是11号文件的scn号,我们来验证一下,我们知道这里面存的是16进制,我们用科学计算器将c1ba3700转换成10进制看一下,发现结果是12696119,这和之前查的11号文件的scn 3652289不一致啊。问题出现在哪里了呢?上一篇文章我们已经提到过linux是小字节序的,这意味着实际存的数是反过来的,那现在我们将c1ba3700反过来再转成10进制看看,即将37bac1转换成10进制,我们发现刚好就是3652289。


       接下来就好办啦,我们只需要将12号文件头的对应位置改为c1ba3700即可。



       现在只需要将fcb63700改为c1ba3700即可:


modify  x  c1ba37




sum apply   ---重新生成校验值

verif



       至此我们已经修改完成啦,现在我们开库:

         


      可以看到,12号文件已经可以recover并且开库后,12号文件也已经被online。最后我们再来检查下数据文件的scn信息:


select file#,to_char(checkpoint_change#),name,status from v$datafile;



至此该问题已经完美解决。




       本来是想分享些sql优化相关的知识点及案例的,奈何笔者目前太菜,还接触不到太多有意思的案例,暂时只能先分享点其他的内容,大家且看且珍惜哈,说不定哪天就坚持不下去了







最后修改时间:2020-11-25 10:44:31
文章转载自取名浪费我半小时,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论