问题背景: 客户数据库环境遭遇断电宕机,启动数据库失败,协助查看。 报错如下:
Total System Global Area 6442450944 bytes Fixed Size 8807168 bytes Variable Size 1375735040 bytes Database Buffers 5049942016 bytes Redo Buffers 7966720 bytes Database mounted. ORA-00742: Log read detects lost write in thread 1 sequence 1202 block 137840 ORA-00312: online log 18 thread 1: '/u01/app/oracle/oradata/orcl/redo18.log' alter pluggable database all open * ERROR at line 1: ORA-01109: database not open
问题解决: 宕机过程中redolog丢失
SQL> RECOVER DATABASE UNTIL CANCEL; //尝试recover ORA-01547: 警告: RECOVER 成功但 OPEN RESETLOGS 将出现如下错误 ORA-01152: 文件 1 没有从过旧的备份中还原 ORA-01110: 数据文件 1: '/oracle/oradata/orcl/system01.dbf' SQL> alter database open resetlogs; alter database open resetlogs * 第 1 行出现错误: ORA-01152: 文件 1 没有从过旧的备份中还原 ORA-01110: 数据文件 1: '/oracle/oradata/orcl/system01.dbf'
alert.log中记录如下:
Errors in file /oracle/diag/rdbms/sem/SEM/trace/SEM_pr00_3546.trc: ORA-01547: 警告: RECOVER 成功但 OPEN RESETLOGS 将出现如下错误 ORA-01152: 文件 1 没有从过旧的备份中还原 ORA-01110: 数据文件 1: '/oracle/oradata/SEM/system01.dbf' ORA-1547 signalled during: ALTER DATABASE RECOVER DATABASE UNTIL CANCEL ... Tue Sep 03 03:29:40 2013 Checker run found 15 new persistent data failures
很明显控制文件中的scn没赶上数据文件和数据头文件中的变化 然后尝试不玩全恢复
SQL> recover database using backup controlfile until cancel;
ORA-00279: 更改 6530705 (在 09/01/2013 02:59:56 生成) 对于线程 1 是必需的 ORA-00289:
建议: /oracle/archivelog/1_20_824696280.dbf
ORA-00280: 更改 6530705 (用于线程 1) 在序列 #20 中
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
cancel
介质恢复已取消。
SQL> alter database open resetlogs; --一般情况下到这里就能启动
数据库已更改。 此客户依然报错,尝试强制启动。
报错如下: ERROR at line 1: ORA-01194: file 1 needs more recovery to be consistent ORA-01110: data file 1: '/opt/oracle/oradata/chf/system01.dbf'
修改隐含参数强制启动
SQL> create pfile='/tmp/pfile' from spfile; File created. -------/tmp/pfile中加上---------- _allow_resetlogs_corruption= TRUE --------------------------------- SQL> startup mount pfile='/tmp/pfile' force ORACLE instance started. Total System Global Area 622149632 bytes Fixed Size 2230912 bytes Variable Size 419431808 bytes Database Buffers 192937984 bytes Redo Buffers 7548928 bytes Database mounted.
依然报错: 添加参数 *.undo_management='MANUAL' 启动成功,怀疑为undo表空间损坏 启动成功后重建undo表空间 1.先把数据文件offline,在mount状态下执行:
SQL>alter database datafile '/software/oradata/JLPROJCT/undotbs01.dbf' offline drop ;
2,打开数据库
SQL>alter database open;
3.我们知道一个数据文件对应n个undo段,所有现在已经有好多undo 段已经 offline了,我们先不对他做任何操作,先查看不是offline的undo段,你会发现他们是不是offline的这些undo段是需要恢复(need recover)
SQL> select status,count(*) from dba_rollback_segs group by status; STATUS COUNT(*) ---------------- ---------- ONLINE 23 need recovery 5 OFFLINE 143 SQL>select segment_name,status from dba_rollback_segs where status<>'offline'; 就会发现所有用户回滚段是需要恢复的,状态是need recovery.,这个语句不会显示由于数据文件损坏而出现offline的回滚段。 SEGMENT_NAME STATUS ------------------------------ ---------------- SYSTEM ONLINE ###这是系统回滚段。 _SYSSMU154_3691636531$ need recovery _SYSSMU155_3686385895$ need recovery _SYSSMU156_3796802683$ need recovery _SYSSMU157_2723916652$ need recovery _SYSSMU158_1435464080$ need recovery
4.新建一个回滚表空间,
SQL>create undo tablespace undo2 datafile '/software/oradata/JLPROJCT/undotbs02.dbf' size 100m ; tablespace created
5,把回滚段设置成人工管理,然后删除损坏的回滚段。
SQL>alter system set undo_tablespace= 'undo2' scope=spfile; ##指定成新建的undo表空间。 system altered SQL>alter system set undo_management='manual' scope=spfile; system altered
6,创建pfile
SQL>create pfile='/Oracle/app/pfile.ora from spfile; file created
7,一致性关闭数据库,
SQL>shu immediate
8,在pfile 文件中添加一个隐藏参数,把这些回滚段都列在这个参数值里,
*._offline_rollback_segment=('_SYSSMU154_3691636531$','_SYSSMU155_3686385895$','_SYSSMU156_3796802683$','_SYSSMU157_2723916652$','_SYSSMU158_1435464080$')
9,创建成spfile 然后启动数据库。
SQL>create spfile from pfile; spfile created SQL>startup
10,这时候回滚段数量并没有发生改变,
SQL>select segment_name,status from dba_rollback_segs where status<>'offline'; SEGMENT_NAME STATUS ------------------------------ ---------------- SYSTEM ONLINE _SYSSMU154_3691636531$ need recovery _SYSSMU155_3686385895$ need recovery _SYSSMU156_3796802683$ need recovery _SYSSMU157_2723916652$ need recovery _SYSSMU158_1435464080$ need recovery
11,因为是手工管理,可以直接删除掉那些回滚段。
SQL> drop rollback segment “_SYSSMU154_3691636531$”; rollback segment droped
12,然后删掉原来的undo表空间。
SQL>drop tablespace undo1 including contents;
13,然后重启数据库,
shu immediate startup
14,注意这时候你的undo 管理还是手工的,所以要把之前的修改改正会自动管理。并且把添加的隐含参数*._offline_rollback_segment删掉。
SQL>alter system set undo_management='auto' scope=spfile;
第二种情况:当损坏的undo 表空间的回滚段上还有活动的事务,这种情况就要强行提交这些事务,就会造成一些数据的丢失。 1,启动数据库到mount状态,只能启动到这里, 2,把有问题的回滚段offline
SQL>alter database datafile '/software/oradata/JLPROJCT/undotbs01.dbf' offline drop ;
3,查看回滚段状态,和第一种情况略有不同,她没有offline的回滚段。
SQL>select usn,xacts from v$rollstat; SQL> select status,count(*) from dba_rollback_segs group by status; STATUS COUNT(*) ---------------- ---------- ONLINE 23 need recovery 5 QL>select segment_name,status from dba_rollback_segs where status<>'offline'; SEGMENT_NAME STATUS ------------------------------ ---------------- _SYSSMU154_3691636531$ need recovery _SYSSMU155_3686385895$ need recovery _SYSSMU156_3796802683$ need recovery _SYSSMU157_2723916652$ need recovery _SYSSMU158_1435464080$ need recovery
4,试图创建发现报错,真正工作中可以从这里来判断到底是那种情况,第一种情况是可以重新建立的。 必须先禁止继续使用旧的回滚段和回滚空间:
SQL>create pfile=/oracle/app/pfile.ora from spfile file created SQL>shutdown immediate ;
在pfile中添加并修改以下内容:
*.undo_management='manual' ###手动管理,才可以删除回滚段
*._offline_rollback_segments=('_SYSSMU154_3691636531$','_SYSSMU155_3686385895$','_SYSSMU156_3796802683$','_SYSSMU157_2723916652$','_SYSSMU158_1435464080$') ###这样才能删除这些回滚段
*.undo_tablespace='undo2' ###这样就会让以后的事务不在用旧的回滚段和undo表空间,
5.创建成spfile 然后启动数据库。
SQL>create spfile from pfile; spfile created SQL>startup
6,删除旧的回滚段和回滚表空间:
SQL>drop rollbackup segment '_SYSSMU154_3691636531$' ;
把need recovery 的回滚段全部删除后,
SQL>drop undo tablespace undo1 including contents; ###因为已经丢失,就不必要添加数据文件了(and datafiles 选项了)
7,创建一个新的undo表空间,然后启动数据库,再修改undo_management 为自动。 注意这样后,所有未提交的事务都当做提交处理了。

更多内容请关注微信公众号:数据与人
