字典禁忌:UPDATE GLOBAL_NAME为空之后的恢复
(题图授权来自Oracle VP , Sally Piao的摄影佳作)
编辑手记:最近一个朋友遭遇到了这个问题,当GLOBAL_NAME被更新为空值之后,数据库无法启动,我们重温一下老熊的这个测试,记住结论,无论如何不要Update字典表。
如果你在数据库的告警日志中发现类似如下的提示,那么多半你的PROPS$发生了更改:
Database Characterset is ZHS16GBK
Updating 7.0.0.0.0 NLS parameters in sys.props$
-- adding 10.2.0.5.0 NLS parameters.
在以前的一篇文章中( 数据库链:Database Link与GLOBAL_NAMES参数的关系 ),我提到千万不能将 Oracle 数据库的 global_name 更新为空。这不,事儿来了。我的一个同事,提到了一个解决办法,不过那个办法实际上是一种不完全恢复的办法,如果没有备份,就行不通。如果没有备份,可以使用BBED来修改块来解决这个问题,不过使用 bbed 仍然比较麻烦。
下面是我一时心血来潮进行的一次测试。测试环境,10.2.0.4 for Linux AS 5.5。注意,不要在生产库上模仿。注意:这个方法可能仅适用于10.2.0.4版本。
首先 UPDATE GLOBAL_NAME 为空,COMMIT 后以 abort 方式关闭数据库,以 abort 方式只是为了增加点难度。之后再启动数据库。
启动失败,不出意料出现 ORA-600[18062] 错误:
下面来解决这个问题。
第1步,重启数据库到 MOUNT 状态:
第2步,在另一个窗口中,使用 gdb
第3步,OPEN 数据库:
约等一会儿,在 alert 日志里面可以看到:
在 gdb 的输出可以看到:
第4步,在 gdb 那里中止 OPEN:
sqlplus 会提示:
这一次,Instance 并没有 terminated。只是 Serverprocess 被 KILL 了。
第5步,还原 GLOBAL_NAME:
虽然可以执行 UPDATE,但是不能 COMMIT。再试试能不能做 DDL:
成功了。
在另会一个会话中查看 GLOBAL_NAME:
GLOBAL_NAME 回来了。
这里通过 DDL 的隐式提交特性来 UPDATE GLOBAL_NAME。其实还有更简单的办法:OCI 主动断开连接时的自动提交。如果 UPDATE 之后,直接退出 sqlplus,UPDATEGLOBAL_NAME 的事务实际也提交了。看起来 ORACLE 这时只是不能执行显式的 COMMIT 语句。
第6步,重启数据库:
看起来只能以 abort 方式关闭数据库:
成功了,数据库起来了。没有数据丢失,没有使用备份。不需要基于时间点的恢复,不需要 BBED,不需要 Resetlog。
搜索 盖国强(Eygle)微信号:eeygle,或者扫描下面二维码,备注:云和恩墨大讲堂,即可入群。每周与千人共享免费技术分享,与讲师在线讨论。