Oracle宕机案例汇总(一)

案例一:UNDO坏块导致Oracle无法Open

场景:

周五马上下班了,研发反馈数据库连不上了,由于是公司内部的数据库,所有数据来源于其他库通过expdp/impdp导入得到的,主要用于问题重现处理产品BUG,数据库的特点是数据量大,用户多,几乎每时每刻数据库都在进行impdp和drop user操作,数据允许有部分丢失....,好吧,说了这么多,我只想说数据库没有任何备份,当然也没有启动归档模式;

通过告警日志可以马上定位到UNDO坏块导致的数据库宕机;

ORA-01578: ORACLE data block corrupted (file # 3, block # 280)

ORA-01110: data file 3: '/u02/app/oracle/oradata/orcl11/undotbs01.dbf'

最保险的方式,通过rman备份+归档进行恢复,可以保证数据的一致性。

但是既然没有rman,也是有方法启动数据库的。

数据库在open状态下出现UNDO损坏比较容易解决,只要创建新的UNDO,当前UNDO切换到新创建的UNDO,删除旧的UNDO 就可以解决;

但是当前情况是数据库无法OPEN,只能启动到mount状态

SQL>startup

ORACLE instance started.

Total System Global Area 784998400 bytes

Fixed Size 2257352 bytes

Variable Size 515903032 bytes

Database Buffers 264241152 bytes

Redo Buffers 2596864 bytes

Database mounted.

ORA-01092: ORACLE instance terminated. Disconnection forced

ORA-01578: ORACLE data block corrupted (file # 3, block # 280)

ORA-01110: data file 3: '/u02/app/oracle/oradata/orcl11/undotbs01.dbf'

Process ID: 8265

Session ID: 1 Serial number: 5

显然在mount状态下是不允许创建和删除undo表空间操作

SQL> create undo tablespace UNDOTBS2 datafile '/u02/app/oracle/oradata/orcl11/undotbs02.dbf' size 1M autoextend on;

create undo tablespace UNDOTBS2 datafile '/u02/app/oracle/oradata/orcl11/undotbs02.dbf' size 1M autoextend on

*

ERROR at line 1:

ORA-01109:database not open

SQL> drop tablespace UNDOTBS1 including contents and datafiles;

drop tablespace UNDOTBS1 including contents and datafiles

*

ERROR at line 1:

ORA-01109: database not open

那么在数据库不能open情况下,如何跳过undo坏块,启动数据库呢?

这时可以使用两个隐含参数”_CORRUPTED_ROLLBACK_SEGMENTS”,”_offline_rollback_segments”,两个参数效果很相似。

(1)_CORRUPTED_ROLLBACK_SEGMENTS表示数据库启动时跳过损坏的回滚段,如果无法确认具体哪个回滚段损坏,会选择跳过所有回滚段,具体用法是在参数文件中增加参数,

_CORRUPTED_ROLLBACK_SEGMENTS=(SYSSMU1$, _SYSSMU2$, _SYSSMU3$, ...etc)

具体回滚段名称需要查询得到,

(2)_offline_rollback_segments表示在数据库启动时,可以指定部分回滚段offline;

现在万事具备了,只需要查询出损坏的回滚段名,或查询出所有回滚段名加入到_CORRUPTED_ROLLBACK_SEGMENTS参数中,即可open数据库了。

某些情况下,在undo损坏时,会在告警日志中显示几号回滚段损坏,但是本次没有显示具体回滚段名称;

那么问题来了,如何在mount状态下,查看UNDO回滚段名称?

显然mount状态下是无法直接查询的;

SQL> select * from v$rollname;

select * from v$rollname

*

ERROR at line 1:

ORA-01219: database not open: queries allowed on fixed tables/views only

那么在数据库mount或关闭状态下,如何查询数据库UNDO段名呢?

一般情况下有两种方法:

方法一:使用操作系统命令strings,本次案例数据库操作系统为Redhat6.5;

1.Get SMU information as following command:

[root@chenjch ~]#$strings system01.dbf | grep _SYSSMU | cut -d $ -f 1 | sort -u > listSMU

<=======请替换system01.dbf 文件为您的数据库的system表空间的数据文件。

得到回滚段名后,在执行如下操作即可

2.Add the following parameter in init.ora:

UNDO_MANAGEMENT=MANUAL

_ALLOW_RESETLOGS_CORRUPTION = TRUE

_CORRUPTED_ROLLBACK_SEGMENTS=(SYSSMU1$, _SYSSMU2$, _SYSSMU3$, ...etc)

<=========请替换SYSSMU*$ 为您的数据库中,步骤1查询出来的具体SYSSMU*$ 名称。

3. Startup the database using pfile:

SQL>startup pfile='init.ora'

SQL>show parameter corrupt;

4. Recover and open the database:

SQL>RECOVER DATABASE UNTIL CANCEL;

Cancel

SQL>ALTER DATABASE OPEN RESETLOGS;

方法二:bbed工具,可以在数据库不启动情况下,直接查询或修改数据块部分信息,当然也可以查询UNDO段名称;

11g开始已经没有这个工具了,需要单独下载;

-----Oracle 11g版本,undo$表信息一般位于1号文件第225个数据块中

BBED> set file 1 block 225

FILE# 1

BLOCK# 225

BBED> map

File: /u02/app/oracle/oradata/orcl11/system01.dbf (1)

Block: 225 Dba:0x004000e1

------------------------------------------------------------

KTB Data Block (Table/Cluster)

......

sb2 kdbr[25] @86 -------含有25个UNDO段

......

BBED> p kdbr

sb2 kdbr[0] @86 8078

sb2 kdbr[1] @88 8011

......

sb2 kdbr[23] @132 6537

sb2 kdbr[24] @134 6470

BBED>x /rnc *kdbr[0]----查看号UNDO段名称

col 1[6] @8151:SYSTEM

BBED>x /rnc *kdbr[1]----查看1号UNDO段名称

col 1[20] @8085: _SYSSMU1_4115952380$

......

依次可以查询出所有UNDO段名

参数文件:

#*.undo_tablespace='UNDOTBS1'

#*.undo_management=AUTO

*.undo_tablespace='SYSTEM'

*.undo_management='MANUAL'

*._corrupted_rollback_segments='_SYSSMU1_4115952380$','_SYSSMU2_3882698531$','_SYSSMU3_1780844141$'......'

SQL> shutdown immediate

SQL> startup

ORACLE instance started.

Total System Global Area 784998400 bytes

Fixed Size 2257352 bytes

Variable Size 515903032 bytes

Database Buffers 264241152 bytes

Redo Buffers 2596864 bytes

Database mounted.

Database opened.

总结:

通过bbed工具进行测试,并不是UNDO任何块损坏都会造成数据库宕机,只有段头块损坏会出现这个问题,可以通过下面SQL查看段头块;

selectheader_file,header_block

fromdba_segments

wheresegment_name like'_SYSSMU%'

orderby2;

UNDO损坏可以分为几种情况:

一:open状态下损坏,直接新建,切换,删除即可,或通过备份进行恢复;

二:无法OPEN,使用隐含参数跳过损坏的段,启动数据库,或通过备份进行恢复;

有时UNDO损坏在告警日志中并不会马上报错,之前遇到过数据库服务器断电,来电后启动数据库时open阶段一直卡住并没有任何返回结果,后台告警日志也没有输出日志,在打开另一个sqlplus窗口,检查数据库状态时,发现数据库已经是open状态了,但是所有dml语句都会卡住,无法正常执行,这种情况可以考虑到数据块在异常断电启动恢复实例时,要经过前滚和回滚,前滚结束后就可以open数据库了,然后在进行回滚,而这次情况看上去是前滚已经结束,回滚出现异常,可以猜测是UNDO出现问题,在没有备份的情况下,尝试用_corrupted_rollback_segments也可以解决问题;

第二种方法更详细解释可以看我另一篇博客

http://blog.itpub.net/29785807/viewspace-2128326/

Oracle_UNDO坏块测试和修复(BBED)

欢迎关注我的微信公众号"IT小Chen",共同学习,共同成长!!!