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 查看段头块;
select header_file , header_block
from dba_segments
where segment_name like '_SYSSMU%'
order by 2 ;
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",共同学习,共同成长!!!