背景
某项目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-600[6006]和ora-600[4137]
如果scn号一致以后报ora-600[6006]或ora-600[4137],需要添加:
*.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-600[6006] |
oradebug poke | 直接修改sga中的scn | 11.2.0.4可用 |
反思
这次恢复最终没有完全成功。但过程中学到的教训:
- 没有备份就不要碰生产数据库——这次是从"没备份"开始的灾难链
- scn是oracle的心跳——理解scn的wrap/base结构是处理ora-600[2662]的前提
- oradebug poke是核武器——直接修改sga内存,用错了数据库就彻底废了
- 强制恢复后的数据库不可信——oracle官方建议重建,这不是建议,是忠告
结果:未完全恢复,但积累了宝贵的强制恢复经验
以上就是oracle数据库无备份强制恢复的实战指南的详细内容,更多关于oracle无备份强制恢复的资料请关注代码网其它相关文章!
发表评论