重庆思庄Oracle、KingBase、PostgreSQL、Redhat认证学习论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 303|回复: 0
打印 上一主题 下一主题

[Oracle] Oracle 11g 数据库 UNDO 文件丢失导致无法打开故障处理报告

[复制链接]
跳转到指定楼层
楼主
发表于 2026-1-23 13:16:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式



1. 故障现象 (Symptoms)
数据库实例意外终止,尝试启动数据库时,在 OPEN 阶段报错失败。

报错信息:

ORA-01092: ORACLE instance terminated. Disconnection forced

ORA-00604: error occurred at recursive SQL level 1

ORA-00376: file 3 cannot be read at this time

ORA-01110: data file 3: '/data/oradata/sxhis/undotbs1...'

现象描述: 控制台日志显示 SMON 进程在进行事务恢复(SMON: enabling tx recovery)或崩溃恢复(KCRA)时,由于无法读取文件号为 3 的数据文件(Undo数据文件),导致实例直接 Crash。

2. 故障分析 (Root Cause Analysis)
直接原因: 数据库的 Undo 表空间对应的数据文件(File 3)在操作系统层面丢失或损坏,导致数据库无法通过一致性检查。

深层原因: 数据库在 Open 阶段需要读取 Undo 段(Rollback Segments)来回滚未提交的事务或进行实例恢复。由于文件丢失,Oracle 无法读取这些段头信息,触发 ORA-00376。

难点:

现场没有有效的 RMAN 备份,无法进行标准还原。

系统数据文件(SYSTEM)与控制文件不一致,需要日志应用,但 Undo 又丢失,导致死锁。

回滚段数量巨大(数百个),且名称为非默认的复杂名称(如 _SYSSMU30_2531942408$),手动屏蔽困难。

3. 处理思路与过程 (Troubleshooting Process)
本次恢复采取了“非常规强制恢复”手段,过程经历了以下几个阶段:

尝试 Offline Drop(失败): 尝试将文件3离线并丢弃,但由于数据库处于不一致状态,且存在未提交事务,普通 Offline 无法绕过启动检查。

尝试手动管理 + 默认屏蔽(失败): 修改 PFILE 将 undo_management 设为 MANUAL 并屏蔽默认名称回滚段(_SYSSMU1$等)。失败原因为实际回滚段名称带有时间戳后缀,默认名称无法匹配。

尝试 Event 10513(失败): 使用事件 10513 阻止事务恢复,但卡在 Crash Recovery 阶段(ORA-01194),提示 System 文件需要更多恢复。

尝试组合拳 + 手动抓取名称(部分成功):

使用 _allow_resetlogs_corruption=TRUE 强制跳过一致性检查。

使用 _corrupted_rollback_segments 屏蔽日志中报错的具体段名(如 30号、33号)。

结果: 数据库 Resetlogs 成功,但在 Open 时遇到新的回滚段报错(“打地鼠”现象,屏蔽一个报下一个)。

最终方案(自动化全量屏蔽): 编写 Shell 脚本,从 SYSTEM 数据文件中通过二进制提取工具(strings)和正则表达式(Regex),提取出系统中记录的所有回滚段名称,生成一个包含数百个屏蔽名单的 PFILE,一次性通过启动检查。

4. 最终实施步骤 (Execution Steps)
第一步:生成包含所有回滚段的救援参数文件
在 Linux 终端执行以下脚本,自动生成 PFILE:

Bash

# 1. 准备基础参数
cat > /home/oracle/pfile_rescue.ora <<EOF
*.compatible='11.2.0.4.0'
*.db_block_size=8192
*.db_name='sxhis'
*.control_files='/data/oradata/sxhis/control01.ctl'
*.undo_management='MANUAL'
*.undo_tablespace='UNDOTBS1'
*.diagnostic_dest='/u01/app/oracle'
# 核心救命参数
*._allow_resetlogs_corruption=TRUE
*.event='10513 trace name context forever, level 2'
EOF

# 2. 自动化提取所有回滚段名称并追加到参数文件
# 注意:修改下方 /data/.../system... 为实际 SYSTEM 文件路径
echo -n "*._corrupted_rollback_segments=(" >> /home/oracle/pfile_rescue.ora

strings /data/oradata/sxhis/system.256.916498993 | \
grep -aEo '_SYSSMU[0-9]+_[0-9]+\$' | \
sort | uniq | \
tr '\n' ',' | \
sed 's/,$//' >> /home/oracle/pfile_rescue.ora

echo ")" >> /home/oracle/pfile_rescue.ora



第二步:加载参数并强制打开数据库
进入 SQL*Plus 执行:

SQL

-- 强制中止实例
shutdown abort;

-- 加载救援参数文件
startup mount pfile='/home/oracle/pfile_rescue.ora';

-- 将坏掉的数据文件脱机丢弃
alter database datafile 3 offline drop;

-- 尝试打开数据库(如果提示需Resetlogs则加 resetlogs 关键字)
alter database open;
第三步:重建 Undo 表空间
数据库打开后(Open),立即执行以下操作替换坏掉的表空间:

SQL

-- 1. 创建新的 Undo 表空间 (注意路径)
create undo tablespace UNDOTBS2 datafile '/data/oradata/sxhis/undotbs2.dbf' size 1G autoextend on;

-- 2. 删除旧的损坏表空间
drop tablespace UNDOTBS1 including contents and datafiles;
第四步:恢复正常参数并重启
清洗掉所有隐藏参数,回归正常配置:

创建新的标准 PFILE (/home/oracle/pfile_production.ora):
也可以直接在原pfile文件修改

删除 _allow_resetlogs_corruption

删除 _corrupted_rollback_segments

删除 event='10513...'

修改 undo_management='AUTO'

修改 undo_tablespace='UNDOTBS2'

在 SQL*Plus 中重建 SPFILE 并重启:

SQL

create spfile from pfile='/home/oracle/pfile_production.ora';
shutdown immediate;
startup;
5. 处理结果 (Result)
状态: 数据库成功 Open,用户可正常连接。

数据完整性: 由于使用了 _allow_resetlogs_corruption,可能存在逻辑层面的微小不一致。


6. 后续建议 (Recommendations)
立即备份(高危): 当前数据库属于“带病痊愈”,必须立即执行全库逻辑导出(EXPDP),这是唯一能验证数据逻辑完整性的方法。

Bash

expdp system/password directory=dump_dir full=y dumpfile=full_recover.dmp logfile=full_recover.log
重建数据库: 建议在业务空闲期,利用导出的 DMP 文件,新建一个干净的数据库实例进行导入,彻底消除隐藏参数带来的潜在隐患。


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 支持支持 反对反对
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|重庆思庄Oracle、Redhat认证学习论坛 ( 渝ICP备12004239号-4 )

GMT+8, 2026-4-17 21:11 , Processed in 0.250127 second(s), 20 queries .

重庆思庄学习中心论坛-重庆思庄科技有限公司论坛

© 2001-2020

快速回复 返回顶部 返回列表