如果数据库在打开时,当前undo数据文件坏掉的话,比如UNDOTBS2出现了介质损坏,那么数据库就不能继续DML操作了。如果这时UNDOTBS2表空间上还有active状态的事务(未提交),Oracle会将其下的所有段都标志为NEEDS RECOVERY,这时我们首选使用备份恢复UNDOTBS2,但如果没有备份,那你只能用新建的UNDO替代损坏的UNDO,而损坏UNDO上的未提交事务也将不得不丢弃。如果你想删除这个损坏的UNDO表空间,必须另做处理(需要系统择时重启),我们模拟一下这种情况:
$ rm
undotbs02.dbf
SQL>alter system checkpoint;
cmd端再做update语句时会报错
SQL> update emp1 set sal=1000 where
empno=7902;
ORA-01116: 打开数据库文件3时出错
ORA-01110: 数据文件3:
'/u01/oradata/prod/undotbs02.dbf'
ORA-27041: 无法打开文件
SQL> startup force mount //一定要到mount下
SQL> select file#,checkpoint_change#
from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 6708724
2 6708724
3 6708724
4 6708724
5 6708724
6 6708724
SQL> select file#,checkpoint_change#
from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 6708724
2 6708724
3 0
4 6708724
5 6708724
6 6708724
SQL> alter database datafile 3 offline;
SQL> alter database open;
SQL> select * from v$rollname;
USN NAME
---------- ------------------------------
0 SYSTEM
SQL> select segment_name,status from
dba_rollback_segs; //这个静态视图可以列出所有(online或offline)UNDO段信息
SEGMENT_NAME STATUS
------------------------------
----------------
SYSTEM ONLINE
_SYSSMU20_1357956213$ NEEDS RECOVERY
_SYSSMU19_1357956213$ NEEDS RECOVERY
_SYSSMU18_1357956213$ NEEDS RECOVERY
_SYSSMU17_1357956213$ NEEDS RECOVERY
_SYSSMU16_1357956213$ NEEDS RECOVERY
_SYSSMU15_1357956213$ NEEDS RECOVERY
_SYSSMU14_1357956213$ NEEDS RECOVERY
_SYSSMU13_1357956213$ NEEDS RECOVERY
_SYSSMU12_1357956213$ NEEDS RECOVERY
_SYSSMU11_1357956213$ NEEDS RECOVERY
SQL>create undo tablespace undotbs1
datafile '/u01/oradata/prod/undotbs01.dbf' size 100m autoextend on;
SQL>select * from v$tablespace;
TS# NAME
INC BIG FLA ENC
---------- ------------------------------
--- --- --- ---
0 SYSTEM
YES NO YES
1 SYSAUX
YES NO YES
2 UNDOTBS1YES
NO YES
4 USERS
YES NO YES
3 TEMP
NO NO YES
6 EXAMPLEYES NO
YES
8 TEST
YES NO YES
5 UNDOTBS2YES
NO YES
SQL> alter system set
undo_tablespace=UNDOTBS1;
注意:此时原有活动事务的信息(未提交)可能仍然保存在UNDOTBS2,已经没有恢复的必要了。
SQL> update emp1 set sal=1000 where empno=7902; //emp1表被锁住,不能做DML操作
update emp1 set sal=1000 where empno=7902
*
第1行出现错误:
ORA-00376: 此时无法读取文件7
ORA-01110: 数据文件7:
'/u01/oradata/prod/undotbs02.dbf'
SQL> drop tablespace undotbs2 including
contents and datafiles;
drop tablespace undotbs2 including contents
and datafiles
*
第1行出现错误:
ORA-01548: 已找到活动回退段'SYSSMU11_1357956213$',终止删除表空间
//这个UNDOTBS2删不掉是因为Oracle把其下的所有段都标志成NEEDS RECOVERY了,再查看一下相关的数据字典:
SQL> select segment_name,status from
dba_rollback_segs;
解决有两个办法:1)使用备份恢复,2)使用oracle提供的隐含参数_CORRUPTED_ROLLBACK_SEGMENTS
我们假设没有备份,就使用第2种方法
SQL>create pfile from spfile; //建立静态参数文件
SQL>shutdown abort
#vi /u01/oracle/dbs/init.ora //在静态参数文件里第一行插入以下内容
_CORRUPTED_ROLLBACK_SEGMENTS=(_SYSSMU11_1357956213$,_SYSSMU12_1357956213$,_SYSSMU13_1357956213$,_SYSSMU14_1357956213$,_SYSSMU15_1357956213$,_SYSSMU16_1357956213$,_SYSSMU17_1357956213$,_SYSSMU18_1357956213$,_SYSSMU19_1357956213$,_SYSSMU20_1357956213$)
然后存盘,再使静态参数文件启动数据库
SQL> startup
pfile='/u01/oracle/dbs/init.ora'
SQL> drop rollback segment "_SYSSMU11_1357956213$";
回退段已删除。
......
SQL> drop rollback segment
"_SYSSMU20_1357956213$";
SQL> select segment_name,status from
dba_rollback_segs;
SEGMENT_NAME STATUS
------------------------------
----------------
SYSTEM ONLINE
_SYSSMU10_1384520126$ ONLINE
_SYSSMU9_1384520126$ ONLINE
_SYSSMU8_1384520126$ ONLINE
_SYSSMU7_1384520126$ ONLINE
_SYSSMU6_1384520126$ ONLINE
_SYSSMU5_1384520126$ ONLINE
_SYSSMU4_1384520126$ ONLINE
_SYSSMU3_1384520126$ ONLINE
_SYSSMU2_1384520126$ ONLINE
_SYSSMU1_1384520125$ ONLINE
已选择11行。
SQL> drop tablespace undotbs2 including
contents and datafiles;
表空间已删除。
如果仍然删除失败(比较少见),则尝试修改字典
SQL>select * from v$tablespace; 记下要删除的undo对应的ts#号,比如是=2,则执行下行语句:
SQL>update seg$ set type# = 3 where
ts#=2;
然后再删除该表空间即可。