前几天由于单位断电了,导致一台BK*应用的开发数据库环境无法open打开,本以为借助于advise/repair failure就可以实现恢复,中间还是费了不少周折。
这算是自己第一次处理稍微比较复杂的恢复问题,以前碰见的问题都是比较常规简单的,对于备份恢复来说,一直想找一个时间更系统的学习一下,这个问题处理的过程当中才发现这些基础理论的重要性,因此一些处理步骤上还是比较混乱的,思路并不是很清晰,胡子眉毛一把装,尝试了所有会用或能用的方法,虽然最后拉起了库,但按照惜分飞大师的说法,还是有一些幸运的成分,不得不承认,差距还是很大,因此下面叙述中要有不到位的,还请各位指正。
环境信息: 版本:12.1.0.2.0 用途:开发环境 其他信息:未开启归档模式 现象:上班后开发人员发现start数据库错误,根据网上的信息,做了重建控制文件等操作,但依旧无法启动,系统此时已经有些混乱了,可能都记不太清楚还做了什么。
1.使用LIST/ADVISE/REPAIR FAILURE 尝试使用LIST FAILURE,发现有几个HIGH、CRITICAL的错误,由于未截图,所以只能描述,记得其中一个错误是某个数据文件出现了坏块,另一个错误是控制文件不是最新状态,好像还有个错误是系统表空间SYSTEM出现坏块(印象已经不深了)。 使用ADVISE FAILURE,指出了一些修复的方法和脚本。 然后执行了REPAIR FAILURE,执行了自动修复,发现一直刷屏,等了许久未结束,强制结束后,再次执行LIST FAILURE,发现仍旧存在数据文件坏块的错误。
2.查询有坏块的数据文件信息 使用dbv检测这一个有问题的数据文件,
从V$DATABASE_BLOCK_CORRUPTION视图查看坏块信息,
说明是10号文件的1678871和1678883块,各自有一个坏块。
其中,CORRUPTION_TYPE都是FRACTURED,表示块头看起来是正常,但是块中存在不一致的版本。
使用如下SQL可以查看这些坏块中具体存在什么信息,
说明坏块中存在的一张表使用的索引。
3.尝试修复坏块 尝试重建索引看看,
提示数据文件块损坏,显然这种方式行不通了。 说到修复坏块,江湖上还是有一些神器的,查了下, (1) ODU:ORACLE DATABASE UNLOADER,老熊和dbsnake现在负责维护。 (2) DUL:DATA UNLOADER,Oracle内部的一个非商业化产品。 (3) AUL:也称MyDUL,d.b.c.a(楼方鑫)大神负责维护。 (4) 刘大的PRM-DUL。 (5) bbed,可以做一些数据块修改的工作。 我之前没有用过任何一款,现学起来还是需要些时间。以上软件大部分有免费版,但对数据文件大小有限制,只能做很小的数据恢复,要想全部恢复,就要买license,虽然我和dbsnake是同事,但为了这么个开发库,而且是这么一个我认为在大神看来其实可能很简单的问题,还是别来麻烦别人了,自己选择继续扛下来,也算让自己锻炼一把。
4.尝试屏蔽坏块数据文件 既然是索引,不是数据,尝试下是不是可以屏蔽这个存在坏块的数据文件。 重建控制文件,可以参考eygle的文章《如何获得创建控制文件的脚本并重建控制文件》(http://www.eygle.com/faq/How.To.Backup.and.Recreate.Controlfile.htm)
生成的控制文件模版中有RESETLOGS/NORESETLOGS两种模式,采用noresetlogs脚本的控制文件,执行,
提示open的时候出现了ORA-00600的错误。
再查看alert日志,
…
…
…
出现了一系列ORA-00600的错误,最后由PMON进程结束了数据库实例的操作。我们知道ORA-600除了是我们李老师的网名:)之外,是Oracle中比较著名的一个错误号。可以参考戴老师这篇文章,对600错误有一个比较详细的解释(http://blog.csdn.net/tianlesoftware/article/details/6645809/)。
从报错看,ORA-00600跟着的参数,第一个是4194、4137,从定义看,都是和交易相关,
Primarily the transaction layer is involved with maintaining structures associated with the management of transactions. As with the cache layer , problems encountered in this layer may indicate some kind of issue at a physical level. Thus it is important to try and repeat the same steps to see if the problem recurs.
彭小波大师推荐了一篇MOS文章(Step by step to resolve ORA-600 4194 4193 4197 on database crash (文档 ID 1428786.1)),惜分飞博客文章中有译文(《ORA-600 4194/ORA-600 4193/ORA-600 4137故障解决》http://www.xifenfei.com/2016/08/ora-600-4194-ora-600-4193-ora-600-4137.html)。
描述的就是alert中出现ORA-00600 4xxx错误的原因,
This error indicates that a mismatch has been detected between redo records and rollback (undo) records.
同时给出了解决方案,
Create pfile from spfile to edit create pfile from spfile;
之所以创建新回滚表空间的原因,就是因为他的回滚段序号要高于目前正使用的段,这样在一个交易需要参考已经不存在的回滚段做块清除操作的时候,才会继续完成这项操作。
The reason we create a new undo tablespace first is to use new undo segment numbers that are higher then the current segments being used. This way when a transaction goes to do block clean-out the reference to that undo segment does not exist and continues with the block clean-out.
尝试下操作。 (1) 根据spfile创建pfile,
create pfile from spfile;
(2) 停止实例,编辑文件,增加:
*.undo_management=manual
*.event='10513 trace name context forever, level 2'
使用文件pfile以restrict启动,
SQL> startup restrict pfile=/u01/app/oracle/product/12.1.0/dbhome_1/dbs/initXXXXX.ora
(3) 查看dba_rollback_segs视图,
发现并不是像上面文章说的OFFLINE状态,是PARTLY AVAILABLE,换句话说需要SR?先创建了新的回滚表空间UBDOTBS2再说。
(4) 删除旧回滚表空间错误,
(5) 参考http://www.linuxidc.com/Linux/2014-06/103780.htm,屏蔽这些SYSSMU表空间,pfile文件增加,
(6) 再次重启删除,
SQL> drop tablespace undotbs1 including contents and datafiles;
正常,
(7) 再次重启,切换表空间,
(8) 数据库可以打开了,查询一些应用表,可是报错了,
开始想出的方法是使用
select dbms_metadata.get_ddl('TABLE','XXX','XXX') from dual;
select dbms_metadata.get_ddl('INDEX','XXX','XXX') from dual;
得出原始建表和索引的语句,但数据无法恢复。
(9) 参考http://blog.csdn.net/sdulsj/article/details/52993052,设置10231事件后使用CTAS方式重建表,
再使用表所属用户执行rename创建原表,
记得关闭事件,
此时,表数据可以恢复使用了,
总结: 1.备份恢复的基础,还是需要理解数据库运转的工作原理,出现任何报错,都是有原因,提示的信息非常重要,要能透过现象看出本质。这不是一朝一夕就能掌握的技能,但需要一朝一夕的积累,这块还需要自己多努力学习和实践。 2.还是需要有备份,如果开启了归档,或者有一些冷备,恢复起来就会方便一些。即使这是一套开发库。 3.整个过程还要感谢白鳝、惜分飞、彭小波以及道长的支持。
欢迎关注我的个人微信公众号:bisal的个人杂货铺