# Oracle数据库无备份强制恢复:SCN不一致、oradebug与ORA-600[2662]

Oracle数据库无备份强制恢复实战:SCN不一致、oradebug与ORA-6002662

这不是教程,这是一次真实恢复过程记录。海关项目的Oracle数据库,没有备份,控制文件损坏,日志文件损坏,数据文件有损坏。最终虽然没有完全恢复成功,但过程中积累的SCN机制、oradebug修改SCN、隐藏参数等知识,值得记录。


背景

某项目Oracle数据库挂了。现象:

  • 登录不了(重置了密码,orapwd命令)
  • 启动提示控制文件不一致(复制了备份的控制文件,但这步有问题)
  • 控制文件损坏(发现有数据文件也有损坏,去除后能够建立控制文件)
  • 清理了日志文件
  • 恢复了数据文件
  • 修改了_allow开头的隐藏参数
  • 打开数据报ORA-00600 2662错误

没有RMAN备份,没有expdp导出。只能硬着头皮强制恢复。


一、强制打开数据库的关键步骤

如果实在要强制打开数据库,参考如下关键点,再有其他错误就要一个一个看了,很麻烦。

步骤1:允许resetlogs时有脏数据

复制代码
_alter system set "_allow_resetlogs_corruption"=true scope=spfile;

这个参数允许在open resetlogs时数据文件中有不一致数据。Oracle官方不建议使用,但没备份的时候,这就是最后一根稻草。

步骤2:处理ORA-01555错误

如果出现ORA-01555错误导致数据库无法open,设置:

复制代码
_CORRUPTED_ROLLBACK_SEGMENTS
undo_management = 'MANUAL'

把回滚段标记为损坏,用MANUAL模式绕过自动undo管理。

步骤3:处理ORA-600 2662------SCN不一致

ORA-600 2662是SCN不一致的典型错误。参数含义:

参数 含义
Arg a Current SCN WRAP:当前(控制文件)的SCN WRAP
Arg b Current SCN BASE:当前(控制文件)的SCN BASE
Arg c dependent SCN WRAP:目标SCN WRAP
Arg d dependent SCN BASE:目标SCN BASE

SCN的计算公式:

复制代码
SCN = (SCN_WRAP × 4294967296) + SCN_BASE

其中4294967296 = 2^32。SCN_WRAP是高位,SCN_BASE是低位。当SCN_BASE足够大时,SCN_WRAP就会加1。

处理方法:先通过多次重启open的方法来观察Current SCN BASE增长速度。如果Current SCN BASE和dependent SCN BASE相差不远,重启几次数据库就可能打开。

步骤4:用10015事件加速SCN增长

如果差距较远,mount之后执行:

复制代码
alter session set events '10015 trace name adjust_scn level 10';

然后尝试open。这个事件会加速Current SCN BASE的增长。

步骤5:启用错误模拟让10015事件生效

如果加入10015事件adjust_scn之后,Current SCN BASE增长还是很慢,某些版本必须加入:

复制代码
_allow_error_simulation = TRUE

才能使10015事件生效。

步骤6:用_smu_debug_mode加速SCN WRAP增长

如果Current SCN BASE增长还是很慢:

复制代码
_smu_debug_mode = 268435456

这个参数直接增长SCN WRAP,需要和_allow_error_simulation=true同时使用。

步骤7:用_minimum_giga_scn大步推进

复制代码
_minimum_giga_scn = n

把SCN向前推进nG。只有Current SCN和dependent SCN相差nG时这个参数才起作用,否则无效。

步骤8:处理ORA-6006006和ORA-6004137

如果SCN号一致以后报ORA-6006006或ORA-6004137,需要添加:

复制代码
*.event="10513 trace name context forever,level 2"
*.db_block_checking=false

步骤9:open resetlogs后的建议

对于open resetlogs打开以后的数据库,最好将业务用户导出以后重建数据库,以防止数据库出现不可预知的错误。Oracle官方建议是open resetlogs之后需要重建数据库。


二、Oracle 11.2.0.4的SCN改法------oradebug实战

上面的参数方法在某些版本不够直接。Oracle 11.2.0.4可以用oradebug直接修改SGA中的SCN值。

第一步:计算目标SCN的十六进制值

复制代码
SQL> select to_char(2723797,'XXXXXXXXXXXXXXXX') from dual;

TO_CHAR(2723797,'
-----------------
           298FD5

2723797的十六进制是0x298FD5。

第二步:设置oradebug跟踪自己的进程

复制代码
SQL> oradebug setmypid
Statement processed.

第三步:查看当前SGA中的SCN值

复制代码
SQL> oradebug dumpvar sga kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 ...

当前SCN是0,数据库处于mount状态。

第四步:用oradebug poke直接修改SCN

复制代码
SQL> oradebug poke 0x06001AE70 8 0x0000000000298FD5
BEFORE: [06001AE70, 06001AE78) = 00000000 00000000
AFTER:  [06001AE70, 06001AE78) = 00298FD5 00000000

poke命令的参数:地址、长度、新值。8表示8字节。

第五步:验证修改后的SCN

复制代码
SQL> oradebug dumpvar sga kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00298FD5 00000000 ...

SCN已经从0变成了0x298FD5(即2723797)。

第六步:打开数据库

复制代码
SQL> alter database open;

Database altered.

第七步:验证checkpoint SCN

复制代码
SQL> select checkpoint_change#, checkpoint_change#/1024/1024/1024 SCN_WARP
     from v$database;

CHECKPOINT_CHANGE#   SCN_WARP
------------------ ----------
           2723798 .002536735

数据库成功打开,checkpoint SCN已经更新。


参数速查表

参数/事件 作用 备注
_allow_resetlogs_corruption=TRUE 允许resetlogs时有脏数据 强制打开的最后手段
_allow_terminal_recovery_corruption=TRUE 允许终端恢复时有损坏 配合上面一起用
_CORRUPTED_ROLLBACK_SEGMENTS 标记损坏的回滚段 处理ORA-01555
undo_management=MANUAL 手动undo管理 绕过损坏的undo表空间
event 10015 adjust_scn 加速SCN BASE增长 需要配合_allow_error_simulation
_allow_error_simulation=TRUE 允许内部错误模拟 让10015事件生效
_smu_debug_mode=268435456 直接增长SCN WRAP 配合_allow_error_simulation
_minimum_giga_scn=n SCN向前推进nG 差距大时使用
event 10513 level 2 禁止事务恢复 处理ORA-6006006
oradebug poke 直接修改SGA中的SCN 11.2.0.4可用

反思

这次恢复最终没有完全成功。但过程中学到的教训:

  1. 没有备份就不要碰生产数据库------这次是从"没备份"开始的灾难链
  2. SCN是Oracle的心跳------理解SCN的WRAP/BASE结构是处理ORA-6002662的前提
  3. oradebug poke是核武器------直接修改SGA内存,用错了数据库就彻底废了
  4. 强制恢复后的数据库不可信------Oracle官方建议重建,这不是建议,是忠告

结果:未完全恢复,但积累了宝贵的强制恢复经验

相关推荐
swordbob15 小时前
MySQL字符集陷阱:从Oracle迁移踩坑到utf8mb4强制规范
数据库·sql
牛油果子哥q15 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++
十五年专注C++开发15 小时前
MySql中各种功能用sql语句实现总结
数据库·sql·mysql
数据库小学妹16 小时前
AI时代数据库怎么选?多模融合、数据统一存储与选型实战指南
数据库·人工智能·经验分享·ai
Albert Edison16 小时前
【Redis】Centos7.9 安装 Redis 5 教程
数据库·redis·缓存
云计算磊哥@16 小时前
运维开发宝典026-MySQL02数据库表操作
运维·数据库·运维开发
小二·16 小时前
Redis 内存溢出(OOM)排查与恢复实战
数据库·redis·bootstrap
pqk6V6Vep16 小时前
Redis 分布式锁进阶第一篇讲解
数据库·redis·分布式
giaz14n9X17 小时前
Redis 分布式锁进阶第六十一篇
数据库·redis·分布式
是一个Bug17 小时前
MongoDB:像搭积木一样存数据
数据库·mongodb