使用dbms_backup_restore包恢复丢失控制文件的RMAN备份以及ORA-06553 PLS-801错误
9月30号下午三点多接到通知,有个客户在升级RAC时失败,在升级前使用RMAN对数据库做了全备,升级失败后,该客户的DBA删除了ORACLE_HOME目录,打算重建,并且使用dd命令清除了ASM磁盘的数据。这种情况,RMAN无法直接使用这个备份文件。本文主要记录该案例的恢复过程。
我到客户现场的时候,客户已经将备份文件拷贝到了测试服务器,要求在测试服务器上恢复,并且客户已经删除了测试数据库,只保留了数据库软件、参数文件和密码文件。
1.还原数据文件
由于丢失了控制文件,需要把备份中的数据文件先恢复回来才能重建控制文件,那么就需要先还原数据文件。没有控制文件,RMAN无法使用这个备份,这里使用DBMS_BACKUP_RESTORE包来还原数据文件。
SQL> DECLARE 2 V_DEVICE VARCHAR2(100); 3 V_FINISH BOOLEAN; 4 TYPE T_FILENAMETABLE IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER; 5 V_FILENAMETABLE T_FILENAMETABLE; 6 V_MAXPIECES NUMBER :=3; 7 BEGIN 8 V_FILENAMETABLE(1) :='/backup/827366429_142_1.dbf'; 9 V_FILENAMETABLE(2) :='/backup/827366429_142_2.dbf'; 10 V_FILENAMETABLE(3) :='/backup/827366429_142_3.dbf'; 11 V_DEVICE := SYS.DBMS_BACKUP_RESTORE.DEVICEALLOCATE(); 12 SYS.DBMS_BACKUP_RESTORE.RESTORESETDATAFILE; 13 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(1, '+dg01/hangan/datafile/system01.dbf'); 14 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(2, '+dg01/hangan/datafile/undotbs1.dbf'); 15 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(3, '+dg01/hangan/datafile/sysaux.dbf'); 16 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(4, '+dg01/hangan/datafile/users01.dbf'); 17 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(5, '+dg01/hangan/datafile/undotbs2.dbf'); 18 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(6, '+dg01/hangan/datafile/users02.dbf'); 19 SYS.DBMS_BACKUP_RESTORE.RESTOREDATAFILETO(7, '+dg01/hangan/datafile/system02.dbf'); 20 FOR I IN 1..V_MAXPIECES LOOP 21 SYS.DBMS_BACKUP_RESTORE.RESTOREBACKUPPIECE(V_FILENAMETABLE(I), V_FINISH); 22 IF V_FINISH THEN 23 SYS.DBMS_BACKUP_RESTORE.DEVICEDEALLOCATE; 24 RETURN; 25 END IF; 26 END LOOP; 27 SYS.DBMS_BACKUP_RESTORE.DEVICEDEALLOCATE; 28 END; 29 / PL/SQL procedure successfully completed.
红色部分为备份的全部备份片,蓝色的数字是数据文件号,绿色部分是还原之后的数据文件名,这些在RMAN的备份日志中可以查询到。2.重建控制文件
还原数据文件后,就可以重建控制文件了。
SQL> CREATE CONTROLFILE REUSE DATABASE "MOUKEHU" resetlogs 2 MAXLOGFILES 192 3 MAXLOGMEMBERS 3 4 MAXDATAFILES 1024 5 MAXINSTANCES 32 6 MAXLOGHISTORY 292 7 LOGFILE 8 GROUP 1 '+dg01/hangan/onlinelog/group_1.261.827477397' SIZE 50M, 9 GROUP 2 '+dg01/hangan/onlinelog/group_3.265.827477431' SIZE 50M 10 DATAFILE 11 '+dg01/hangan/datafile/system01.dbf', 12 '+dg01/hangan/datafile/undotbs1.dbf', 13 '+dg01/hangan/datafile/sysaux.dbf', 14 '+dg01/hangan/datafile/users01.dbf', 15 '+dg01/hangan/datafile/undotbs2.dbf', 16 '+dg01/hangan/datafile/users02.dbf', 17 '+dg01/hangan/datafile/system02.dbf' 18 CHARACTER SET ZHS16GBK 19 ; Control file created.
由于丢失了online redo log,所以创建控制文件时必须指定resetlogs方式,否则报错。
3.恢复归档日志
重建控制文件后,数据库自动启动到mount状态,接下来需要还原归档日志文件。
SQL> DECLARE 2 V_DEVICE VARCHAR2(100); 3 V_FINISH BOOLEAN; 4 BEGIN 5 V_DEVICE := SYS.DBMS_BACKUP_RESTORE.DEVICEALLOCATE(); 6 SYS.DBMS_BACKUP_RESTORE.RESTORESETARCHIVEDLOG(DESTINATION => '/home/oracle/archivelog'); 7 SYS.DBMS_BACKUP_RESTORE.RESTOREARCHIVEDLOG(thread => 2, sequence => 255); 8 SYS.DBMS_BACKUP_RESTORE.RESTOREARCHIVEDLOG(thread => 2, sequence => 256); 9 SYS.DBMS_BACKUP_RESTORE.RESTOREBACKUPPIECE('/deslinux/rmanbak/arc_827370014_146_1', V_FINISH); 10 SYS.DBMS_BACKUP_RESTORE.DEVICEDEALLOCATE; 11 END; 12 / PL/SQL procedure successfully completed.
归档日志还原后,就可以恢复数据库了。
4.恢复数据库
RMAN> run { 2> set until sequence 255 thread 1; 3> set until sequence 260 thread 2; 4> recover database; 5> } executing command: SET until clause using target database control file instead of recovery catalog executing command: SET until clause Starting recover at 30-SEP-13 allocated channel: ORA_DISK_1 channel ORA_DISK_1: sid=150 devtype=DISK starting media recovery archive log thread 1 sequence 254 is already on disk as file /home/oracle/archivelog/1_254_802624418.dbf archive log thread 2 sequence 259 is already on disk as file /home/oracle/archivelog/2_259_802624418.dbf archive log filename=/home/oracle/archivelog/1_254_802624418.dbf thread=1 sequence=254 archive log filename=/home/oracle/archivelog/2_259_802624418.dbf thread=2 sequence=259 media recovery complete, elapsed time: 00:00:04 Finished recover at 30-SEP-13
数据库成功恢复。
5.打开数据库
成功恢复数据库后,就可以以resetlogs方式打开数据库了。
RMAN> alter database open resetlogs; database opened
数据库成功打开,但是经测试,只有sys用户可以访问数据库,业务用户无法连接数据库,通过观察告警日志,发现ORA-06553: PLS-801错误。
Mon Sep 30 21:28:01 2013 Errors in file /10g/admin/hangan/bdump/hangan_mmon_22106.trc: ORA-06553: PLS-801: 内部错误 [56319] Mon Sep 30 21:28:01 2013 Errors in file /10g/admin/hangan/bdump/hangan_mmon_22106.trc: ORA-06553: PLS-801: 内部错误 [56319] Mon Sep 30 21:28:42 2013 Errors in file /10g/admin/hangan/bdump/hangan_j000_1152.trc: ORA-12012: error on auto execute of job 1 ORA-06553: PLS-801: internal error [56319] Mon Sep 30 21:29:42 2013 Errors in file /10g/admin/hangan/bdump/hangan_j000_1152.trc: ORA-12012: error on auto execute of job 3 ORA-06553: PLS-801: internal error [56319]
通过查询MOS,发现这个问题是由于核心对象失效导致的,MOS给出的解决方案是运行utlip.sql和utlrp.sql脚本来重新编译失效对象。
utlip.sql脚本需要在升级模式下运行。
SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SQL> startup upgrade ORACLE instance started. Total System Global Area 536870912 bytes Fixed Size 2022112 bytes Variable Size 155190560 bytes Database Buffers 373293056 bytes Redo Buffers 6365184 bytes Database mounted. Database opened. SQL> @?/rdbms/admin/utlip.sql
utlrp.sql脚本需要数据库在读写模式下运行。
SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SQL> startup ORACLE instance started. Total System Global Area 536870912 bytes Fixed Size 2022112 bytes Variable Size 155190560 bytes Database Buffers 373293056 bytes Redo Buffers 6365184 bytes Database mounted. Database opened. SQL> @?/rdbms/admin/utlrp.sql
此时,数据库失效对象已经成功重新编译,数据库可以正常使用。