Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1083698
  • 博文数量: 227
  • 博客积分: 6860
  • 博客等级: 准将
  • 技术积分: 2688
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-02 16:06
文章分类

全部博文(227)

文章存档

2015年(7)

2014年(8)

2012年(5)

2011年(62)

2010年(145)

分类: Oracle

2011-03-14 16:16:58

前一段时间解决了一个ORA-1122错误,正好本机的数据库环境由于Windows的自动重起,导致数据库无法打开,出现错误信息也是ORA-1122

这次出现错误的表空间是UNDO表空间。

上一篇介绍了利用备份进行恢复的方法,这篇尝试重建UNDO表空间的方法。

UNDO表空间的ORA-1122错误解决(一):http://yangtingkun.itpub.net/post/468/455691


由于数据库存在备份,因此可以轻松的对数据库进行恢复,不过难得碰到一个错误的情况,尝试一下是否可以在缺少备份的基础上进行数据库的恢复:

再看一下问题,尝试打开数据库,则会报错:

SQL> CONN /@TEST AS SYSDBA已连接到空闲例程。
SQL> STARTUP MOUNT
ORACLE
例程已经启动。

Total System Global Area 76619308 bytes
Fixed Size 454188 bytes
Variable Size 50331648 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
数据库装载完毕。
SQL> ALTER DATABASE OPEN;
ALTER DATABASE OPEN
*
ERROR
位于第 1 :
ORA-01122:
数据库文件 2 验证失败

ORA-01110:
数据文件 2: 'F:ORACLEORADATATESTUNDOTBS01.DBF'
ORA-01200: 25600
的实际文件大小小于26880块的正确大小

如果没有备份,那么就只能采用其他的方式来进行恢复,如果出现问题的数据文件中的内容不是关键内容的话,也可以考虑使用ALTER DATABASE DATAFILE OFFLINE的方式。

方法可以参考一个类似的案例:一次ORA-1122错误的解决:http://yangtingkun.itpub.net/post/468/455467

不过这里出现问题的是UNDO表空间,如果UNDO表空间中没有要回滚的数据,那么问题比较简单,因为Oracle可以更换UNDO表空间,只需要直接将UNDO表空间的数据文件OFFLINE,启动数据库后,新建一个UNDO表空间,并切换当前的UNDO表空间即可。

但是如果UNDO表空间中记录了要回滚的数据,那么恢复操作就会更复杂了。

尝试OFFLINE出现问题的数据文件:

SQL> ALTER DATABASE DATAFILE 'F:ORACLEORADATATESTUNDOTBS01.DBF' OFFLINE;

数据库已更改。

SQL> ALTER DATABASE OPEN;

数据库已更改。

下面可以为系统创建新的UNDO表空间,并实现切换:

SQL> CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE 'F:ORACLEORADATATESTUNDOTBS02.DBF' SIZE 200M;

表空间已创建。

SQL> SHOW PARAMETER UNDO_TABLESPACE

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTBS1
SQL> ALTER SYSTEM SET UNDO_TABLESPACE = UNDOTBS2;

系统已更改。

虽然数据库已经启动完成,UNDO表空间也已经切换,但是问题并没有结束,如果尝试删除UNDO表空间UNDOTBS1则会报错:

SQL> DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS AND DATAFILES;
DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS AND DATAFILES
*
ERROR
位于第 1 :
ORA-01548:
已找到活动回退段'_SYSSMU1$',终止删除表空间


SQL> SELECT COUNT(*) FROM YANGTK.T;
SELECT COUNT(*) FROM YANGTK.T
*
ERROR
位于第 1 :
ORA-00376:
此时无法读取文件
2
ORA-01110:
数据文件 2: 'F:ORACLEORADATATESTUNDOTBS01.DBF'

在查询包括需要进行回滚操作的表时,同样会遇到错误。而对于其他没有问题的表,则可以正常访问:

SQL> SELECT COUNT(*) FROM YANGTK.T1;

COUNT(*)
----------
20

现在问题就是前面所提到的,OFFLINEUNDO表空间中保存着需要进行回滚的记录,而这些记录会导致数据库部分内容还没有最终恢复完成,在此之前受影响的部分对象是无法正常访问的。

SQL> SELECT SEGMENT_NAME, OWNER, TABLESPACE_NAME, STATUS
2 FROM DBA_ROLLBACK_SEGS;

SEGMENT_NAME OWNER TABLESPACE_NAME STATUS
-------------------- ------ -------------------- ----------------
SYSTEM SYS SYSTEM ONLINE
_SYSSMU1$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU2$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU3$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU4$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU5$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU6$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU7$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU8$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU9$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU10$ PUBLIC UNDOTBS1 NEEDS RECOVERY
_SYSSMU11$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU12$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU13$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU14$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU15$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU16$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU17$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU18$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU19$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU20$ PUBLIC UNDOTBS2 ONLINE

已选择21行。

检查系统的回滚段信息,发现UNDOTBS1中的所有回滚段都需要恢复。在没有备份的情况下,只能尝试使用隐含参数将数据库打开,不过这个过程会破坏数据库的一致性,而且可能造成数据库出现逻辑错误。采用下面的方法打开数据库后,应该马上执行EXP备份,重建数据库后,再导入。

下面开始尝试恢复数据库,首先创建PFILE,并关闭数据库:

SQL> CREATE PFILE='F:INITTEST.ORA' FROM SPFILE;

文件已创建。

SQL> SHUTDOWN IMMEDIATE数据库已经关闭。已经卸载数据库。
ORACLE
例程已经关闭。

手工编辑PFILE,修改UNDO_MANAGEMENTMANUAL,并添加隐含参数_OFFLINE_ROLLBACK_SEGMENTS=(_SYSSMU1$,_SYSSMU2$,……_SYSSMU10$)

*.undo_management='MANUAL'
_offline_rollback_segments=(_SYSSMU1$,_SYSSMU2$,_SYSSMU3$,_SYSSMU4$,_SYSSMU5$,_SYSSMU6$,_SYSSMU7$,_SYSSMU8$,_SYSSMU9$,_SYSSMU10$)

下面重起数据库:

SQL> STARTUP PFILE=F:INITTEST.ORA
ORACLE
例程已经启动。

Total System Global Area 76619308 bytes
Fixed Size 454188 bytes
Variable Size 50331648 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
数据库装载完毕。数据库已经打开。

由于设置了隐含参数,现在可以删除回滚段了:

SQL> DROP ROLLBACK SEGMENT "_SYSSMU1$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU2$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU3$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU4$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU5$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU6$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU7$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU8$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU9$";

回退段已删除。

SQL> DROP ROLLBACK SEGMENT "_SYSSMU10$";

回退段已删除。

下面就可以删除UNDOTBS1表空间了:

SQL> DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS AND DATAFILES;

表空间已丢弃。

表空间删除后,通过重起来去掉加载的隐含参数。至此,恢复操作告一段落:

SQL> SHUTDOWN IMMEDIATE数据库已经关闭。已经卸载数据库。
ORACLE
例程已经关闭。
SQL> STARTUP
ORACLE
例程已经启动。

Total System Global Area 76619308 bytes
Fixed Size 454188 bytes
Variable Size 50331648 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
数据库装载完毕。数据库已经打开。
SQL> SHOW PARAMETER UNDO

NAME TYPE VALUE
------------------------------------ ----------- --------------
undo_management string AUTO
undo_retention integer 10800
undo_suppress_errors boolean FALSE
undo_tablespace string UNDOTBS2
SQL> SELECT COUNT(*) FROM YANGTK.T;

COUNT(*)
----------
1273614

由于数据库处于逻辑损害的状态,而且使用了隐含参数,很可能造成未知的危害,因此这个时候应该对数据库中的全部数据执行导出操作,然后重建数据库,再导入回去。

即使采用了上面的操作,也无法确保数据库中数据的一致性。这是由于采用了上面的恢复方法,导致UNDO表空间中记录的需要回滚的信息丢失,而这部分对应的数据会被认为是已经提交的数据,从而破坏了数据库的事务性。

上一篇文章采用恢复的方法打开数据库后,查询T表的记录是:

SQL> SELECT COUNT(*) FROM YANGTK.T;

COUNT(*)
----------
636807

这里不难看出二者的差别有多大。因此,这种方法的恢复,只是没有备份时不得已而为之。

原址:http://yangtingkun.itpub.net/post/468/455743

阅读(1034) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~