Oracle Undo问题总结(ORA-600 4xxx 系列错误)
一、概述
本文聚焦于Oracle数据库中最棘手的故障之一:与回滚段(Undo Segment)密切相关的ORA-600 4xxx 内部错误 。这类错误通常导致数据库无法正常打开或运行,属于非常规恢复(Unofficial Recovery) 的范畴。
核心问题:ORA-600 4xxx 错误基本都与回滚段的管理、状态或数据一致性有关。它们可能源于:
- 回滚段本身的物理或逻辑损坏
- Redo与Undo记录之间的不匹配
- 数据字典中关于回滚段的元数据不一致
- 硬件故障或异常断电导致的写丢失(Lost Write)
重要警示 :本文讨论的方法涉及使用隐含参数、事件(Event)乃至BBED工具修改数据字典,风险极高 ,可能导致数据库进一步损坏或数据永久丢失。这些操作应仅在无有效备份、且数据库无法通过常规手段恢复时,作为最后手段使用。
二、常见ORA-600 4xxx 错误详解
ORA-600 4xxx 错误是 Oracle 的内部错误,通常表示核心代码中出现了意外情况。其中,4xxx 系列的错误大多与回滚段(Undo)相关,处理起来较为棘手。以下是几种常见的错误类型及其含义:
- ORA-600 4000 a
- 含义: 这是 Undo 相关问题中最严重的一种。它表示 Oracle 在尝试撤销数据字典表(如
bootstrap$)时,根据其 ITL(Interested Transaction List)中的信息寻找 Undo Segment Number 失败。参数[a]即为失败的 Undo Segment Number。 - 影响: 通常会导致数据库无法启动,因为自举(bootstrap)过程失败。
- 严重程度与处理建议:极高。常需使用BBED修改数据字典。
- 含义: 这是 Undo 相关问题中最严重的一种。它表示 Oracle 在尝试撤销数据字典表(如
- ORA-600 4193 a b
- 含义: 检测到 Redo 记录与 Rollback (Undo) 记录之间存在不匹配。Oracle 正在将 Redo 中记录的 Undo Block Sequence Number 与 Undo 块中的 Sequence Number 进行验证,但验证失败。
- 参数:
[a]为 Undo 记录序列号,[b]为 Redo 记录序列号。 - 严重程度与处理建议:高。通常表明回滚段损坏,可通过重建Undo表空间解决。
- ORA-600 4194 a b
- 含义: 同样表示 Redo 记录与 Rollback (Undo) 记录不匹配。Oracle 正在将 Redo 块中的 Undo 记录号与 Undo 块中记录的最大 Undo 记录号进行验证,但验证失败。
- 参数:
[a]为 Undo 块中的最大记录号,[b]为 Redo 块中的记录号。 - 严重程度与处理建议:高。与4193类似,通常通过重建Undo表空间解决。
- ORA-600 4137
- 含义: 在回滚一个 Undo 记录时,发现事务 ID 不匹配。这可能表明回滚段本身或回滚段正尝试应用 Undo 记录的对象存在损坏。
- 严重程度与处理建议:高。同样表明回滚段损坏,需隔离并重
- ORA-600 4097
- 含义: 涉及的事务 ID (XID) 和序列号来自 Undo 段头。通常发生在数据库崩溃后,系统回滚段的事务表出现问题。当访问回滚段头以检查事务是否已提交时,发现给定的 XID 处于事务跟踪的"未来"。
- 严重程度与处理建议:极高。常需使用BBED修改数据字典。
三、解决方法(仅供参考)
处理此类问题应遵循由简到繁、风险由低到高的原则。以下方案按推荐顺序排列。
1. 将回滚段管理方式改为手动
首先尝试将数据库的 Undo 管理方式从自动(AUTO)切换为手动(MANUAL),这有时可以绕过自动 Undo 管理中的某些检查。
-
从 SPFILE 创建 PFILE:
sqlCREATE PFILE='/tmp/init.ora' FROM SPFILE; -
编辑 PFILE (
/tmp/init.ora),添加或修改以下参数:UNDO_MANAGEMENT = MANUAL UNDO_TABLESPACE = SYSTEM -
使用修改后的 PFILE 启动数据库:
sqlSTARTUP PFILE='/tmp/init.ora';如果启动不成功,则继续尝试下一步。
2. 尝试设置隐含事件(Event)
通过设置一系列 1051x 事件,可以禁止 SMON 进程在启动时执行某些恢复和清理操作,从而可能成功打开数据库。
-
在 PFILE 中添加以下事件条目:
EVENT='10513 trace name context forever, level 2:10512 trace name context forever, level 1:10511 trace name context forever, level 2:10510 trace name context forever, level 1' -
事件说明:
10510: 关闭 SMON 对离线挂起(pending offline)回滚段的检查。10511: 关闭 SMON 清理 Undo 字典的检查。10512: 关闭 SMON 收缩回滚段的检查。10513: 禁止 SMON 进程回滚未提交的事务。
-
使用修改后的 PFILE 启动数据库。如果仍不成功,则继续下一步。
3. 使用参数屏蔽回滚段
使用 _offline_rollback_segments 或 _corrupted_rollback_segments 参数,让 Oracle 在启动时忽略指定的回滚段
-
在 PFILE 中添加问题回滚段的名称,例如:
_offline_rollback_segments=('_SYSSMU1_3780397527$', '_SYSSMU2_2232571081$') -
回滚段名称获取方式:
-
数据库打开状态: 查询
DBA_ROLLBACK_SEGMENTS或V$ROLLNAME视图。 -
数据库关闭状态: 使用
strings命令从SYSTEM01.DBF文件中提取:strings system01.dbf | grep _SYSSMU | cut -d $ -f 1 | sort -u
-
-
使用修改后的 PFILE 启动数据库。如果依然无法打开,则需考虑更高级的方法。
4. 使用 BBED 工具修复数据字典
如果上述方法均无效,特别是遇到 ORA-600 4000 错误时,可能需要使用 BBED(Block Browser and Editor)工具直接修改数据文件块,以修复数据字典中的不一致。此操作风险极高,修改前必须备份所有相关文件!
- 操作目标: 通常是修改
BOOTSTRAP$或其他核心字典对象所在的数据块,将其中指向损坏回滚段的事务信息标记为已提交或直接清除。
5. 使用 DUL 工具抽取数据
这是最后的补救措施。当数据库完全无法启动且 BBED 也无法修复时,可以使用 DUL(Data UnLoader)等工具直接读取数据文件,绕过数据库实例,将数据抽取出来,然后重建数据库并导入。
四、注意事项
-
后续清理工作:
数据库成功启动后,务必完成以下扫尾工作,以确保数据库长期稳定运行:
- 将出问题的回滚段
OFFLINE并DROP掉。 - 创建一个新的 Undo 表空间。
- 将数据库的 Undo 表空间切换到新建的表空间。
- 将
UNDO_MANAGEMENT参数改回AUTO。 - 最后,使用 SPFILE 正常重启数据库。
- 将出问题的回滚段
-
数据字典一致性检查: 如果在解决过程中使用了 BBED 修改了数据字典,强烈建议使用
hcheck.sql等脚本检查数据字典的一致性,观察是否还有其他 600 错误出现,并据此判断是否需要重建数据库。
五、MOS 文档参考
以下是 Oracle Metalink (MOS) 上关于这些错误的官方文档摘要:
ORA-600 4000 a
- 版本: 6.0 至 9.2
- 描述: 这是一个非常严重的错误,表示 Oracle 尝试在字典缓存中查找 Undo 段号但失败。
- 参数:
[a]为 Undo 段号。 - 功能: 内核事务 Undo。
- 影响: 实例失败,无法重启。
- 建议:
- 此错误可能发生在对从其他数据库传输过来的表空间执行 DML 操作时。在 8.1.7.4, 9.0.1.4 和 9.2.0.1 版本中已修复。
- 变通方法是在目标数据库中创建更多的回滚段,直到其最高回滚段号(
select max(US#) from sys.undo$;)至少与源数据库中的最高 US# 一样高。 - 也可能是内存损坏导致,尝试重启实例。
- 如果数据库无法启动,请立即联系 Oracle 支持服务,并提供
alert.log和相关跟踪文件。
已知 Bug
| Bug ID | 修复版本 | 描述 |
|---|---|---|
| 16761566 | 11.2.0.3.9, 11.2.0.4, 12.1.0.2 | 实例因 ORA-600 4000 usn# 无法启动 |
| 13910190 | 11.2.0.3.BP15, 11.2.0.4 | Exadata 中插入的表空间引发 ORA-600 4000 |
| 14741727 | 11.2.0.2.9, 11.2.0.3.BP12 | Bug 12326708 和 14624146 的修复可能导致问题 |
| 10425010 | 11.2.0.3, 12.1.0.1 | Exadata FlashCache 可能返回过期数据块 |
| 9145541 | 11.1.0.7.4, 11.2.0.2 | 11g 中 CREATE CONTROLFILE 后,插入的数据文件出现 OERI4000 |
| 7687856 | 11.2.0.1 | 对传输的 ASSM 表空间执行 DML 时出现 ORA-600 4000 |
ORA-600 4193 a b
- 版本: 6.0 至 10.1
- 描述: 检测到 Redo 记录与 Rollback (Undo) 记录不匹配。
- 功能: 内核事务 Undo。
- 影响: 进程失败,可能的回滚段损坏。
- 建议: 此错误可能表示回滚段损坏,可能需要从备份中恢复。请提交跟踪文件和
alert.log给 Oracle 支持服务进行进一步分析。
已知 Bug
| Bug ID | 修复版本 | 描述 |
|---|---|---|
| 14034244 | 11.2.0.3.BP09, 11.2.0.4 | 11.2.0.3 中使用 ASM 时发生 Lost write 类型损坏 |
| 8240762 | 10.2.0.5, 11.1.0.7.10 | Undo 损坏,伴随 ORA-600 4193/4194/4137 或 SMON 自旋 |
ORA-600 4194 a b
- 版本: 6.0 至 10.1
- 描述: 检测到 Redo 记录与 Rollback (Undo) 记录不匹配。
- 功能: 来自缓存层的内核事务 Undo。
- 影响: 进程失败,可能的回滚段损坏。
- 建议: 同 ORA-600 4193。
已知 Bug
| Bug ID | 修复版本 | 描述 |
|---|---|---|
| 8240762 | 10.2.0.5, 11.1.0.7.10 | Undo 损坏,伴随 ORA-600 4193/4194/4137 或 SMON 自旋 |
| 3210520 | 9.2.0.5, 10.1.0.2 | RAC 中可能出现 OERIkjccqmg:esm / OERI4194 / 损坏 |
ORA-600 4137
- 版本: 7.0 至 10.1
- 描述: 回滚时发现事务 ID 不匹配,表明回滚段或相关对象损坏。
- 功能: 内核事务 Undo 恢复。
- 影响: 回滚段可能物理损坏。
- 建议:
- 可能由 Undo 段的"Lost write"引起。
- 主要方法是识别包含坏 Undo 块的文件,并将其视为文件损坏处理。
- 如果处于归档模式,还原文件并前滚。
- 如果处于非归档模式,从错误发生前的冷备份中还原。
- 查询
DBA_ROLLBACK_SEGS,如果状态为 "NEEDS RECOVERY",可参考 Note 28812.1。
已知 Bug
| Bug ID | 修复版本 | 描述 |
|---|---|---|
| 8240762 | 10.2.0.5, 11.1.0.7.10 | Undo 损坏,伴随 ORA-600 4193/4194/4137 或 SMON 自旋 |
| 671491 | 8.1.6.0 | 如果回滚段扩展区超过 32767 个,可能发生 OERI:4194 |
"Step by step to resolve ORA-600 4194 4193 4197" 总结
此部分详细说明了在数据库崩溃后,如何通过创建新的 Undo 表空间来解决 ORA-600 4194/4193 错误。
症状 (SYMPTOMS)
alert.log 中出现以下错误,随后数据库崩溃:
ORA-00600: internal error code, arguments: [4194], [#], [#], [], [], [], [], []
该错误表示 Redo 记录与 Undo 记录不匹配。
变更 (CHANGES)
此问题通常发生在断电或硬件故障导致数据库崩溃后。在启动时,数据库执行正常的前滚(Redo),然后在回滚(Undo)阶段生成此错误。
原因 (CAUSE)
此问题也可能由以下缺陷引起:Bug 8240762: 在执行 SHRINK 操作后,Undo 块可能被两个不同的事务使用,导致 ORA-600 4193/4194 等内部错误。
解决方案 (SOLUTION)
最佳实践是创建一个新的 Undo 表空间。此方法包含段检查。
-
从 SPFILE 创建 PFILE 以便编辑:
CREATE PFILE FROM SPFILE; -
关闭实例:
SHUTDOWN IMMEDIATE; -
在 PFILE 中设置以下参数:
undo_management = manual event = '10513 trace name context forever, level 2' -
使用修改后的 PFILE 启动数据库到受限模式:
STARTUP RESTRICT PFILE='<initsid.ora>'; -
检查回滚段状态:
SELECT tablespace_name, status, segment_name FROM dba_rollback_segs WHERE status != 'OFFLINE';关键: 除了
SYSTEM回滚段,所有 Undo 段都应为OFFLINE。如果存在PARTLY AVAILABLE或NEEDS RECOVERY状态的段,请联系 Oracle 支持。 -
创建新的 Undo 表空间:
CREATE UNDO TABLESPACE <new_undo_tablespace> DATAFILE '<datafile_path>' SIZE 2000M; -
删除旧的 Undo 表空间:
DROP TABLESPACE <old_undo_tablespace> INCLUDING CONTENTS AND DATAFILES; -
关闭数据库:
SHUTDOWN IMMEDIATE; -
启动到 MOUNT 状态,并修改 PFILE 指向新的 Undo 表空间:
STARTUP MOUNT; ALTER SYSTEM SET undo_tablespace = '<new_tablespace>' SCOPE=PFILE; -
关闭并正常启动数据库:
SHUTDOWN IMMEDIATE; STARTUP; -- 使用正常的 SPFILE 启动
原理说明: 首先创建一个新的 Undo 表空间,是为了使用比当前段号更高的新 Undo 段号。这样,当事务尝试进行块清除(block clean-out)时,其对旧 Undo 段的引用将不存在,从而可以顺利完成块清除操作。