Oracle UNDO 数据文件丢失处理(案例一)

Oracle UNDO 数据文件丢失处理(案例一)

本文档详细阐述了在 Oracle 数据库归档模式下,因 shutdown abort 导致 UNDO 数据文件丢失后的恢复步骤。此场景较为特殊,处理不当可能导致数据不一致,操作需谨慎。

一、案例环境

  • 操作系统: Linux x86-64
  • 数据库版本: Oracle 11gR2
  • 归档模式: Archivelog

二、案例过程概述

  1. 创建测试表并插入数据,模拟一个未提交的事务。
  2. alter system flush buffer_cache;刷新缓存,确保数据写入磁盘
  3. 使用 shutdown abort 命令强制关闭数据库。
  4. 模拟 UNDO 数据文件丢失(例如,使用 mv 命令移动文件)。
  5. 数据库mount状态下offline drop掉undo数据文件
  6. alter database open打开数据库
  7. 完成后续处理

三、核心概念:两个关键的隐藏参数

在处理 UNDO 段损坏或丢失的问题时,Oracle 提供了两个隐藏参数:_offline_rollback_segments_corrupted_rollback_segments。理解它们的区别至关重要。

当数据库启动(OPEN)时,任何在这两个参数中列出的回滚段(Rollback Segments)都会:

  • 不会被扫描,其上的活动事务既不会被标记为死亡,也不会被回滚。
  • 在数据字典表 undo$ 中显示为 OFFLINE 状态。
  • 不能被实例用于新的事务。

_offline_rollback_segments 参数

  • 核心行为 : 在数据库 OPEN 阶段,Oracle 仍然会尝试读取 此参数列出的 UNDO 段。
  • 事务处理:
    • 如果查询数据块时发现活跃事务,并指向这些 UNDO 段,Oracle 会尝试读取其事务表。
    • 若事务已提交,则进行数据块清除(Block Cleanout)。
    • 若事务仍活动,则生成一致性读(CR)块。
    • 关键点 : 如果读取这些 UNDO 段时发生错误(如文件丢失或块损坏),错误会被记录到 alert.log 中,但不会阻止数据库启动。然而,查询该数据的会话会因错误而终止。

_corrupted_rollback_segments 参数

  • 核心行为 : 在数据库 OPEN 阶段,Oracle 完全不会访问 此参数列出的 UNDO 段。
  • 事务处理:
    • 所有指向这些 UNDO 段的事务都被假定已经提交
    • 这会进行延迟块清除(Delayed Block Cleanout),效果类似于该回滚段已被删除。
  • 风险警告 : 此方法极易导致严重的逻辑数据不一致 。如果数据字典或自举(bootstrap)核心对象上有活跃事务,数据库可能无法打开(报 ORA-00704 错误)。强烈建议在使用此参数打开数据库后,立即导出数据并重建数据库。

四、案例详细步骤

以下示例演示了使用 _offline_rollback_segments 参数进行恢复的完整流程。

1. 模拟 UNDO 数据文件丢失

sql 复制代码
-- 1. 创建测试表并插入数据
SQL> create table test as select * from dba_objects;
Table created.

SQL> select count(*) from test;
  COUNT(*)
----------
     71896

SQL> insert into test select * from test; -- 未提交事务
71896 rows created.

SQL> alter system flush buffer_cache; -- 刷新缓存,确保数据写入磁盘
System altered.

SQL> quit

-- 2. 强制关闭数据库
SQL> shutdown abort;
ORACLE instance shut down.

-- 3. 在操作系统层面模拟文件丢失
[oracle@netdbhost dbs]$ mv /u01/test/test/undotbs1.dbf /u01/test/test/undotbs1.dbfbak

2. 启动数据库报错

尝试启动数据库时,会因找不到 UNDO 数据文件而报错。

sql 复制代码
SQL> startup
ORACLE instance started.
...
Database mounted.
ORA-01157: cannot identify/lock data file 3 - see DBWR trace file
ORA-01110: data file 3: '/u01/test/test/undotbs01.dbf'

3. 将丢失的数据文件 OFFLINE DROP

MOUNT 状态下,将丢失的数据文件离线并删除。此操作允许数据库继续打开。

sql 复制代码
-- 查询确认丢失的文件名
SQL> select name from v$datafile where file#=3;

NAME
----------------------------------------------------
/u01/test/test/undotbs01.dbf

-- 执行 offline drop
SQL> alter database datafile '/u01/test/test/undotbs01.dbf' offline drop;
Database altered.

4. 打开数据库并检查 UNDO 段状态

此时数据库可以成功打开,但需要检查 UNDO 段的状态。

sql 复制代码
SQL> alter database open;
Database altered.

-- 查看回滚段状态,会发现大量 NEEDS RECOVERY 状态的段
SQL> select status, count(*) from dba_rollback_segs group by status;

STATUS             COUNT(*)
------------------ ----------
NEEDS RECOVERY             10
ONLINE                      1

-- 查看具体的回滚段名称
SQL> select segment_name, status from dba_rollback_segs where status='NEEDS RECOVERY';

SEGMENT_NAME                     STATUS
-------------------------------- -----------------
_SYSSMU1_3780397527$             NEEDS RECOVERY
_SYSSMU2_2232571081$             NEEDS RECOVERY
... (共10个)

5. 创建新的 UNDO 表空间

创建一个新的 UNDO 表空间,并切换过去。

sql 复制代码
-- 创建新的 UNDO 表空间
SQL> create undo tablespace undo2 datafile '/u01/test/test/undo2.dbf' size 50m;
Tablespace created.

-- 切换当前实例使用的 UNDO 表空间
SQL> alter system set undo_tablespace='undo2';
System altered.

-- 为后续操作,将 UNDO 管理方式改为手动(需重启生效)
SQL> alter system set undo_management=manual scope=spfile;
System altered.

6. 使用 PFILE 和隐藏参数重启数据库

这是最关键的一步。通过创建 PFILE 并添加 _offline_rollback_segments 参数,告知 Oracle 忽略那些丢失的回滚段。

sql 复制代码
-- 从 SPFILE 创建 PFILE
SQL> create pfile='/home/oracle/dhtest.ora' from spfile;
File created.

-- 关闭数据库
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

编辑 /home/oracle/dhtest.ora 文件,确保包含以下两行(_offline_rollback_segments 的值为上一步查出的所有 NEEDS RECOVERY 的段名):

复制代码
*.undo_management=manual
*._offline_rollback_segments=('_SYSSMU1_3780397527$','_SYSSMU2_2232571081$','_SYSSMU3_2097677531$','_SYSSMU4_1152005954$','_SYSSMU5_1527469038$','_SYSSMU6_2443381498$','_SYSSMU7_3286610060$','_SYSSMU8_2012382730$','_SYSSMU9_1424341975$','_SYSSMU10_3550978943$')

使用修改后的 PFILE 启动数据库:

sql 复制代码
SQL> startup pfile=/home/oracle/dhtest.ora
ORACLE instance started.
...
Database mounted.
Database opened.

-- 验证数据,会发现未提交的数据被视为已提交
SQL> select count(*) from dh.test;
  COUNT(*)
----------
    143792

-- 再次检查回滚段状态,原 NEEDS RECOVERY 的段已变为 OFFLINE
SQL> select status, count(*) from dba_rollback_segs group by status;

STATUS             COUNT(*)
------------------ ----------
NEEDS RECOVERY             10
OFFLINE                    10
ONLINE                      1

7. 手工删除丢失的 UNDO 段

现在可以安全地删除那些已离线的回滚段。

sql 复制代码
SQL> drop rollback segment "_SYSSMU1_3780397527$";
Rollback segment dropped.
-- ... 依次删除所有10个回滚段 ...
SQL> drop rollback segment "_SYSSMU10_3550978943$";
Rollback segment dropped.

-- 确认删除结果
SQL> select status, count(*) from dba_rollback_segs group by status;

STATUS             COUNT(*)
------------------ ----------
OFFLINE                    10
ONLINE                      1

8. 清理并恢复正常配置

最后,删除旧的 UNDO 表空间,并恢复自动 UNDO 管理模式。

sql 复制代码
-- 删除旧的 UNDO 表空间及其数据文件
SQL> drop tablespace undotbs1 including contents and datafiles;
Tablespace dropped.

-- 关闭数据库
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

-- 使用 SPFILE 正常启动
SQL> startup
ORACLE instance started.
...
Database mounted.
Database opened.

-- 将 UNDO 管理改回自动模式
SQL> alter system set undo_management=auto scope=spfile;
System altered.

-- 再次重启使配置生效
SQL> shutdown immediate;
SQL> startup

至此,数据库恢复完毕,UNDO 表空间丢失的问题已解决。

相关推荐
richard_first1 小时前
Transformer与大语言模型:第18章 向量数据库
数据库·人工智能·自然语言处理·transformer·embedding
El Shaddai.plus1 小时前
达梦数据库的执行计划操作符介绍
数据库·oracle
神仙别闹2 小时前
基于 QT(C++)开发的地铁换乘系统
数据库·c++·qt
Token掘金室2 小时前
Function Calling完整调用教程
大数据·数据库·人工智能
钱栈up2 小时前
qoder CLI 1.0.45 本地小说生成工作流搭建:Feature Gate 配置与长文本断连排查从死锁到全流程跑通:Python德州扑克项目的优化
java·前端·数据库
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之自定义数据库表结构实现认证
java·数据库·spring
2501_930472443 小时前
上云迁移验收-CVM健康校验用例与数据库比对报告
数据库·人工智能·阿里云·云计算·腾讯云
anxiao_m3 小时前
不同行业适配哪些云桌面?四大主流品牌场景适配详解
网络·数据库·人工智能
weixin199701080164 小时前
《Mercari OTA 直连接入:日本二手电商出海的API通道与600次/分钟限流实战》(附Python源码)
开发语言·数据库·python