1818IP-服务器技术教程,云服务器评测推荐,服务器系统排错处理,环境搭建,攻击防护等

当前位置:首页 - 数据库 - 正文

君子好学,自强不息!

概述

本文将给大家介绍oracle各类文件损坏的现象和应对策略,请注意所有的恢复都是基于有备份的情况,所以请开启数据库的日常备份。

文章将从以下文件展开:

a. 密码文件

b. 参数文件

c. 控制文件

d. 数据文件(分普通表空间数据文件,其它表空间数据文件如system、sysaux、undo)

e. 日志文件(分current、active、inactive)

在正式实验之前,我先问一个问题,上面这些文件,哪个损坏最致命?欢迎在文末留言处留言。

环境准备

本实验在oracle 11G归档模式下进行,实验前先对数据库做个全库备份。

创建一个普通表空间和一些测试表createtablespacetbs01datafile'/u01/app/oracle/oradata/orcltest/tbs01.dbf'size500m;createtablescott.t01tablespacetbs01asselect*fromdba_objectswhererownum<=100;RMAN>backupdatabase;//全库备份RMAN>listbackup;//查看备份

BSKeyTypeLVSizeDeviceTypeElapsedTimeCompletionTime-------------------------------------------------------------21Full1.14GDISK00:01:3317-MAR-20BPKey:21Status:AVAILABLECompressed:NOTag:TAG20200317T133425PieceName:/home/oracle/backupdir/ORCLTEST_2750922031_133_1_20200317_1035293665.bkpListofDatafilesinbackupset21FileLVTypeCkpSCNCkpTimeName---------------------------------1Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/system01.dbf2Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/sysaux01.dbf3Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/undotbs01.dbf4Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/users01.dbf5Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/example01.dbf6Full160691317-MAR-20/u01/app/oracle/oradata/orcltest/tbs01.dbfBSKeyTypeLVSizeDeviceTypeElapsedTimeCompletionTime-------------------------------------------------------------22Full9.73MDISK00:00:0217-MAR-20BPKey:22Status:AVAILABLECompressed:NOTag:TAG20200317T133602PieceName:/home/oracle/backupdir/c-2750922031-20200317-00SPFILEIncluded:Modificationtime:17-MAR-20SPFILEdb_unique_name:ORCLTESTControlFileIncluded:CkpSCN:1606985Ckptime:17-MAR-20

密码文件损坏

文件说明:密码文件存储的是sys密码

模拟故障:清空该文件

echo''>$ORACLE_HOME/dbs/orapworcltest//orcltest是该数据库的实例名

现象:使用sys通过oracle net登录报密码错误

sqlplus sys/123456@10.40.16.120:1521/orcltest as sysdba

SQL*Plus:Release11.2.0.4.0ProductiononTueMar1713:57:522020Copyright(c)1982,2013,Oracle.Allrightsreserved.ERROR:ORA-01017:invalidusername/password;logondeniedEnteruser-name:

修复:使用自带工具orapwd重新生成密码文件

orapwdfile=$ORACLE_HOME/dbs/orapworcltestpassword=123456force=y//force=y如果原密码文件存在,强制覆盖

参数文件损坏

文件说明:这里所说的参数文件指的是spfile,该文件存储的是实例启动的参数和控制文件的路径

模拟故障:清空该文件

echo''>$ORACLE_HOME/dbs/spfileorcltest.ora

现象:修改数据库参数时会报错

SQL>altersystemsetopen_cursors=400;altersystemsetopen_cursors=400*ERRORatline1:ORA-01565:errorinidentifyingfile'/u01/app/oracle/product/11.2.0/db_1/dbs/spfileorcltest.ora'ORA-27046:filesizeisnotamultipleoflogicalblocksizeAdditionalinformation:1

修复:使用rman还原参数文件

RMAN>listbackupofspfile;BSKeyTypeLVSizeDeviceTypeElapsedTimeCompletionTime-------------------------------------------------------------22Full9.73MDISK00:00:0217-MAR-20BPKey:22Status:AVAILABLECompressed:NOTag:TAG20200317T133602PieceName:/home/oracle/backupdir/c-2750922031-20200317-00SPFILEIncluded:Modificationtime:17-MAR-20SPFILEdb_unique_name:ORCLTEST

RMAN>restorespfileto'/home/oracle/spfileorcltest.ora'from'/home/oracle/backupdir/c-2750922031-20200317-00';
mv/home/oracle/spfileorcltest.ora/u01/app/oracle/product/11.2.0/db_1/dbs/
SQL>shutdownimmediate
SQL>startup

注意在还原spfile的时候如果还原到spfile原先的位置,会报ORA-32011: cannot restore SPFILE to location already being used by the instance

所以需要还原到一个新的路径,然后手工移过去

PS:参数文件也可以从内存中直接创建一个新的,更省事(create spfile=’/home/oracle/spfileorcltest.ora’ from memory;)

控制文件损坏

文件说明:控制文件记录数据库文件的信息和日志的信息等

查看控制文件

SQL>showparametercontrol_files
NAMETYPEVALUE
-----------------------------------------------------------------------------
control_filesstring/u01/app/oracle/oradata/orclte
st/control01.ctl

模拟故障:将该文件清空

echo''>/u01/app/oracle/oradata/orcltest/control01.ctl

现象:前台正常的增删改查不受影响,但一旦出现切换日志或产生检查点时数据库宕机

SQL>altersystemswitchlogfile;altersystemswitchlogfile*ERRORatline1:ORA-03113:end-of-fileoncommunicationchannelProcessID:3433SessionID:1Serialnumber:5

数据库alert日志

TueMar1717:39:062020Errorsinfile/u01/app/oracle/diag/rdbms/orcltest/orcltest/trace/orcltest_ckpt_3415.trc:ORA-00202:controlfile:'/u01/app/oracle/oradata/orcltest/control01.ctl'ORA-27072:FileI/Oerror...LGWR(ospid:3413):terminatingtheinstanceduetoerror227TueMar1717:40:372020Systemstatedumprequestedby(instance=1,osid=3413(LGWR)),summary=[abnormalinstancetermination].SystemStatedumpedtotracefile/u01/app/oracle/diag/rdbms/orcltest/orcltest/trace/orcltest_diag_3403_20200317174037.trcDumpingdiagnosticdataindirectory=[cdmp_20200317174037],requestedby(instance=1,osid=3413(LGWR)),summary=[abnormalinstancetermination].InstanceterminatedbyLGWR,pid=3413

可以看到ckpt这个进程最先发现控制文件损坏了,实例之后被lgwr进程杀掉。可能大家在做实验的时候发现实例是被ckpt杀掉,这也是有可能的,反正可以肯定的一点是,实例最后肯定会挂掉

修复:使用rman还原控制文件

rmantarget/
RMAN>startupnomount
RMAN>restorecontrolfilefrom'/home/oracle/backupdir/c-2750922031-20200317-00';
RMAN>alterdatabasemount;
RMAN>recoverdatabase;//这一步其实是使用archivedlog+redolog对控制文件进行恢复
RMAN>alterdatabaseopenresetlogs;

说明:

a. 不要使用删控制文件的方式去模拟该实验,这是由于ckpt、lgwr进程已经打开了控制文件,内存中已经有了这个控制文件的镜像,而rm命令并不能把这些进程已经打开的控制文件的句柄删掉。所以你会发现实例并没有挂掉。

b. 对数据库resetlogs之后,之前的备份就作废了,所以应该第一时间对数据库做一个全备。

c. 可能大家也注意到了,该实验中只有一个controlfile,当controlfile被破坏了之后,实例就挂了。如果是controlfile的多路复用,其中一个controlfile坏了数据库又是什么影响?我这里先说下我的结论:controlfile只要有一个坏了,实例就会奔溃,同时在alert日志中会提示具体是哪个controlfile损坏,解决办法就是复制一份好的controlfile去替换损坏的controlfile,重新启库即可。实验就留给大家自己做吧。附一段我实验的alert日志(ORA-00227: corrupt block detected in control file: (block 1, # blocks 1) ORA-00202: control file: ‘/u01/app/oracle/oradata/orcltest/control02.ctl’)

总结:

1. 控制文件恢复不会丢失任何事务,但会要求数据库resetlogs,这将会导致之前的备份片无效,所以恢复控制文件后最好做一个全库备份。

2. 对控制文件最好设置两个,一个坏了还能利用另一个恢复,对数据库的影响和恢复的时间都是最小的。

数据文件损坏

为了继续实验,请手工删除之前所有的归档日志和备份文件,并对现在的数据库做一个全备

RMAN>backupdatabase;//全库备份

6.1 普通数据文件损坏

模拟故障:将该文件清空

echo ” > /u01/app/oracle/oradata/orcltest/tbs01.dbf // tbs01是一个普通表空间数据文件

现象:查询该数据文件上的对象报错

SQL>select*fromscott.t01;//t01表在tbs01.dbf文件上select*fromscott.t01*ERRORatline1:ORA-01115:IOerrorreadingblockfromfile(block#)ORA-01110:datafile6:'/u01/app/oracle/oradata/orcltest/tbs01.dbf'ORA-27072:FileI/OerrorAdditionalinformation:4Additionalinformation:130

修复:先对数据文件offline,然后使用rman还原恢复,最后online

SQL>alterdatabasedatafile6offline;RMAN>restoredatafile6;RMAN>recoverdatafile6;SQL>alterdatabasedatafile6online;

6.2 system表空间数据文件损坏

模拟故障:将该文件清空

echo''>/u01/app/oracle/oradata/orcltest/system01.dbf

现象:查询数据字典报错

SQL>select*fromdba_users;select*fromdba_users*ERRORatline1:ORA-00604:erroroccurredatrecursiveSQLlevel1ORA-01115:IOerrorreadingblockfromfile(block#)ORA-01110:datafile1:'/u01/app/oracle/oradata/orcltest/system01.dbf'ORA-27072:FileI/OerrorAdditionalinformation:4Additionalinformation:95524

修复:先关库,然后使用rman还原恢复,最后启库

SQL>shutdownabortSQL>startupmountRMAN>restoredatafile1;RMAN>recoverdatafile1;SQL>alterdatabaseopen;

6.3 sysaux和undo表空间数据文件损坏

sysaux表空间的文件损坏处理手段与普通表空间数据文件损坏处理手段相同,undo表空间的文件损坏处理手段与system表空间数据文件损坏处理手段相同,因为undo表空间的数据文件也不能offline。限于篇幅省略实验步骤,仅贴出文件损坏的现象。

sysaux表空间文件损坏现象:访问sysaux表空间的对象报错

SQL>select*fromsys.WRI$_OPTSTAT_HISTHEAD_HISTORY;
ERROR:
ORA-01578:ORACLEdatablockcorrupted(file#2,block#986)
ORA-01110:datafile2:'/u01/app/oracle/oradata/orcltest/sysaux01.dbf'

undo表空间文件损坏现象:所有修改操作全部报错

SQL>insertintoscott.t01select*fromscott.t01;insertintoscott.t01select*fromscott.t01*ERRORatline1:ORA-00603:ORACLEserversessionterminatedbyfatalerrorORA-01578:ORACLEdatablockcorrupted(file#3,block#144)ORA-01110:datafile3:'/u01/app/oracle/oradata/orcltest/undotbs01.dbf'ORA-01578:ORACLEdatablockcorrupted(file#3,block#144)ORA-01110:datafile3:'/u01/app/oracle/oradata/orcltest/undotbs01.dbf'ProcessID:2835SessionID:20Serialnumber:85

日志文件损坏

7.1 inactive或active日志文件损坏

查看当前日志状态:current-当前正在写入的日志组,active-还未归档的日志组,inactive-已归档的日志组

SQL>selecta.group#,a.member,b.statusfromv$logfilea,v$logbwherea.group#=b.group#orderbygroup#;
GROUP#MEMBERSTATUS
------------------------------------------------------------------------
1/u01/app/oracle/oradata/orcltest/redo01.logINACTIVE
2/u01/app/oracle/oradata/orcltest/redo02.logCURRENT
3/u01/app/oracle/oradata/orcltest/redo03.logINACTIVE

模拟故障:将inactive日志文件清空

echo''>/u01/app/oracle/oradata/orcltest/redo03.log

现象:当数据库切换到该日志组时,数据库并不知道磁盘上的日志文件有问题,只是将内容写到日志文件在内存的拷贝中,等到切换的时候,日志文件落盘就会发现该日志是有问题的,然后alert日志出现报错,不过不影响数据库正常运行,只是以后数据库切换日志会跳过该日志组

SQL>insertintoscott.t01select*fromscott.t01;//重复对一张表进行插入,模拟产生大量的日志

观察alert日志

Errorsinfile/u01/app/oracle/diag/rdbms/orcltest/orcltest/trace/orcltest_arc0_9006.trc:
ORA-00313:openfailedformembersofloggroup3ofthread1
ORA-00312:onlinelog3thread1:'/u01/app/oracle/oradata/orcltest/redo03.log'
ORA-27048:skgfifi:fileheaderinformationisinvalid
Additionalinformation:12
Masterarchivalfailure:313
SQL>altersystemswitchlogfile;

查看v$log,可以看到group 3一直没有被用到

修复:将该日志文件重新初始化

SQL>alterdatabaseclearunarchivedlogfilegroup3;//active的日志损坏也是类似处理,使用该命令后数据库归档会断,所以在恢复日志组后,应立即进行全库备份。

7.2 current日志文件损坏

为了继续实验,请手工删除之前所有的归档日志和备份文件,并对现在的数据库做一个全备

RMAN>backupdatabase;//全库备份

查看当前日志状态

SQL>selecta.group#,a.member,b.statusfromv$logfilea,v$logbwherea.group#=b.group#orderbygroup#;GROUP#MEMBERSTATUS------------------------------------------------------------------------1/u01/app/oracle/oradata/orcltest/redo01.logINACTIVE2/u01/app/oracle/oradata/orcltest/redo02.logINACTIVE3/u01/app/oracle/oradata/orcltest/redo03.logCURRENTSQL>createtablescott.t02asselect*fromdba_users;

模拟故障:current日志文件清空

echo''>/u01/app/oracle/oradata/orcltest/redo03.log

现象:前台正常的增删改查不受影响,但一旦出现切换日志数据库宕机

SQL>createtablescott.t03asselect*fromdba_users;SQL>altersystemswitchlogfile;altersystemswitchlogfile*ERRORatline1:ORA-03113:end-of-fileoncommunicationchannelProcessID:3758SessionID:1Serialnumber:9

查看alert日志

Errorsinfile/u01/app/oracle/diag/rdbms/orcltest/orcltest/trace/orcltest_lgwr_8969.trc:
ORA-00316:log2ofthread1,type0inheaderisnotlogfile
ORA-00312:onlinelog2thread1:'/u01/app/oracle/oradata/orcltest/redo02.log'
LGWR(ospid:8969):terminatingtheinstanceduetoerror316
InstanceterminatedbyLGWR,pid=3458

恢复:使用不完全恢复打开

sqlplus/assysdba
SQL>startupmount
SQL>recoverdatabaseuntilcancel;//不完全恢复

SQL>alterdatabaseopenresetlogs;//会发现启库失败alterdatabaseopenresetlogs*ERRORatline1:ORA-01194:file1needsmorerecoverytobeconsistentORA-01110:datafile1:'/u01/app/oracle/oradata/orcltest/system01.dbf'

这个时候就需要加入隐含参数,再启动

SQL>altersystemset"_allow_resetlogs_corruption"=truescope=spfile;SQL>shutdownabortSQL>startupmountSQL>recoverdatabaseuntilcancel;//不完全恢复输入cancelSQL>alterdatabaseopenresetlogs;

说明:

a. 使用该方式恢复的库,可能会造成数据的丢失,而且也并不能保证一定成功。

b. 恢复成功后,应将表全部使用expdp导出,重建库。

c. 上面的实验每个日志组都只有一个member,如果每个日志组有两个member又是什么样子呢?

先说下我的结论:损坏其中任何一个member对数据库没什么影响,只是在切换到有member损坏的日志组时,会在alert日志中提示告警ORA-00313 ORA-00312 ORA-27048,解决办法就是删掉这个member,重新添加,不需要对数据库进行重启,实验过程我就不展示了。所以最好是每组日志中设置2个成员。

这儿我有个疑问想不通:对inactive的日志进行破坏,数据库切换到这个被破坏的日志时,数据库正常写,只是在日志切换的时候报错,这个能理解,因为系统内存中有这个被破坏的日志之前的拷贝,所有的写可能都是在内存中。切换的时候该日志文件就必须要落盘,所以提示报错。而对current的日志进行破坏,数据库也正常写,但是在日志切换的时候数据库直接崩了。没弄懂这两个为什么会有这个区别。

总结

1. 生产中应制定好备份策略

2. 控制文件和日志文件最好是设置大于一个成员

3. 当前日志组损坏最为致命,如果日志写很繁忙,可以只为日志文件配置一个成员,但同时需要配置一个dataguard,方便切换

4. 此博客仅为个人理解,如有不对的地方,欢迎大家指出

本文来源:1818IP

本文地址:https://www.1818ip.com/post/10898.html

免责声明:本文由用户上传,如有侵权请联系删除!

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。