如果oracle在运行中很不幸遇到undo损坏,当然最好的方法是完全恢复,不过如果没有备份,可以采用一种非常规的手段(利用oracle的隐藏参数),如果此时undo包含未提交的事务,会造成一点点的数据丢失(一般都是可忍受的),如果没有未提交的事务,则不会有数据丢失。其主要步骤有:
1. 修改undo表空间管理为手动;
2. 设置隐藏参数(_offline_rollback_segments或_corrupted_rollback_segments)标识受影响的回滚段,使oracle忽略其上的未提交事务;
3. 手动删除受影响的回滚段和undo表空间,然后重建新的undo表空间;
4. 还原undo表空间管理为自动。
实验如下:
step 1.
如果undo数据文件损坏,数据库只能到mount状态,open时会出现以下错误:
ora-01157: cannot identify/lock data file 14 – see dbwr trace file
ora-01110: data file 14: ‘i:\intel_data\o06dms0\undo1.o06dms0’
说明该undo文件已经损坏或丢失,把该文件offline之后就可以打开数据库了:
sql> alter database datafile ‘i:\intel_data\o06dms0\undo1.o06dms0’ offline drop;
sql> alter database open;
打开数据库的目的是为了找出受影响的回滚段:
sql> select segment_name,status from dba_rollback_segs;
segment_name status
—————————— —————-
system online
_syssmu10_1201331463$ offline
_syssmu9_2926456744$ offline
_syssmu8_640224757$ offline
_syssmu7_3984293596$ offline
_syssmu6_3694658906$ offline
_syssmu5_3475919656$ offline
_syssmu4_168502732$ offline
_syssmu3_1987193959$ offline
_syssmu2_3908286755$ offline
_syssmu1_3281912951$ offline
sql> show parameter undo
name type value
———————————— ———– ————-
undo_management string auto
undo_retention integer 900
undo_tablespace string undo1
关闭数据库:
sql> shutdown immediate;
step 2.
创建一个临时的pfile:
sql> create pfile=’h:\inito06dms0.ora’ from spfile;
修改pfile如下:
*.undo_management=’manual’ — undo表空间管理方式修改为手动
*.undo_tablespace=’undo2′ –指定一个新的undo表空间
*._offline_rollback_segments=(‘_syssmu10_1201331463$’,’_syssmu9_2926456744$’,’_syssmu8_640224757$’,’_syssmu7_3984293596$’,’_syssmu6_3694658906$’,’_syssmu5_3475919656$’,’_syssmu4_168502732$’,’_syssmu3_1987193959$’,’_syssmu2_3908286755$’,’_syssmu1_3281912951$’) –把所有受影响的回滚段都列在这里
并以改pfile重新启动数据库:
sql> startup pfile=’h:\inito06dms0.ora’
step 3.
手动删除受影响的回滚段:
sql>drop rollback segment “_syssmu10_1201331463$”;
sql>drop rollback segment “_syssmu9_2926456744$”;
sql>drop rollback segment “_syssmu8_640224757$”;
sql>drop rollback segment “_syssmu7_3984293596$”;
sql>drop rollback segment “_syssmu6_3694658906$”;
sql>drop rollback segment “_syssmu5_3475919656$”;
sql>drop rollback segment “_syssmu4_168502732$”;
sql>drop rollback segment “_syssmu3_1987193959$”;
sql>drop rollback segment “_syssmu2_3908286755$”;
sql>drop rollback segment “_syssmu1_3281912951$”;
手动删除旧的undo表空间:
sql> drop tablespace undo1 including contents;
重建新的undo表空间:
sql> create undo tablespace undo2 datafile ‘i:\intel_data\o06dms0\undo2.o06dms0’ size 100m;
创建新的spfile,覆盖旧的spfile:
sql> create spfile from pfile=’h:\inito06dms0.ora’;
关闭数据库:
sql> shutdown immediate;
step 4.
以原来的spfile启动数据库:
sql> startup;
还原undo表空间管理为自动:
sql> alter system set undo_management=’auto’ scope=spfile;
取消隐藏参数的设置:
sql> alter system reset “_offline_rollback_segments” scope=spfile;
重启使其生效:
sql> shutdown immediate;
sql> startup
sql> show parameter undo
name type value
———————————— ———– ——————-
undo_management string auto
undo_retention integer 900
undo_tablespace string undo2
最终检查一下:
sql> select segment_name,status from dba_rollback_segs;
segment_name status
—————————— —————-
system online
_syssmu40_1968985325$ online
_syssmu39_4040503138$ online
_syssmu38_4059847715$ online
_syssmu37_2692202156$ online
_syssmu36_2617425201$ online
_syssmu35_1133967719$ online
_syssmu34_1916939664$ online
_syssmu33_99444166$ online
_syssmu32_162619813$ online
_syssmu31_830375278$ online