Oracle 实用技巧之不知道密码情况下 dblink 的迁移

在 Oracle 数据库的运维过程中,常常会有一些特殊场景,需要我们灵活运用知识去解决问题,今天,就和大家一起探讨分析一种情况。我们需要将一个数据库从一个环境迁移到另外一个,但因为种种限制因素,只能采用数据导入导出的方式来进行。在梳理环境编写迁移方案的时候,遇到了一个难题,数据库里有大量的 dblink,大家知道这些 dblink 是在使用的,但是没有人知道密码。下面,我们使用模拟环境来表达分析解决过程。

 

数据库版本:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第1张图片

数据库链接:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第2张图片


知识点:当 GLOBAL_NAMES 参数设置为 TRUE 时,使用 DATABASE LINK 时,DATABASE LINK 的名称必须与被连接库的 GLOBAL_NAME 一致。有兴趣的同学可以详细参考老熊的博客文章http://www.laoxiong.net/database_link_global_names.html

 

在模拟环境中共有3数据库链接,我们以 source 这个为例。首先,我们确定这个 dblink 是可用的:



这个时候,很多同学可能就想到了,既然数据库链接 source 可以用,那就说明本地库(9i,服务名 firefox)是知道访问远程库(11g,服务名 source)时用到的用户名和密码的,那么 Oracle 会把它存在哪里呢?难道是 dba_db_links 的其它列?我们一起来看看:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第3张图片

owner 列存储 dblink 的所有者,值 public 代表是公共的;

db_link 列存储 dblink 的名字;

username 列存储 dblink 访问远程库的用户名;

host 列存储 dblink 远程库的连接字符串,或者本地服务名;

create 列存储列 dblink 的创建时间;

 

dba_db_links 中对于 dblink 以哪个用户访问哪个库都做了详细的保存,但就是没有密码信息。到这里我们不要失望,因为我们知道所有的数据字典其实都不是真正的表格,而是基于内部表的一系列视图。我们去看看 dba_db_links 的定义:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第4张图片

知识点:其实数据字典严格的名字应该叫数据字典视图,它提供了数据库的一些系统信息,数据字典是基于数据字典基表(也叫内部表,以$结尾)所建立的一系列视图,数据字典视图主要包括三种类型: user_xxx,all_xxx 和 dba_xxx。

 

原来 dba_db_links 的数据来自于 link$ 和 user$ 两个内部表,那么密码会不会在这两个表里保存?我们去看看它们的结构:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第5张图片

Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第6张图片


知识点:内部表,sys 用户下以$结尾的一系列表,是数据库内核的组成部分,用户只能在上面执行查询操作,其维护和修改是系统自动完成的,对其的不当操作可能会造成数据库宕机、甚至永久性损坏。

 

在 link$ 和 user$ 中我们发现都有一个 password 字段,那么哪一个是我们要找的 dblink 的密码呢?我们先来看看其中的内容:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第7张图片


内容太多,只选取相关的部分。


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第8张图片

我们发现 link$ 中的密码以明文保存,user$ 中的密码以加密后的字符串保存。但到底哪个才是我们要找的密码呢?其实 Oracle 在设计内部表时每个都有明确的作用和定义,其中 link$ 是用来保存 dblink 相关信息的(包括密码),user$ 是用来数据库本地用户相关信息的。

 

那么现在我们就找到了数据库链接 source 的密码:tiger,再根据其它信息,可以很快写出其迁移重建语句:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第9张图片


知识点:在 10gR1 及之前的版本里,所有 dblink 的密码都是以明文方式在 sys.link$ 中存储,但是在 10gR2 及之后版本,Oracle 进行了改良,以加密方式存储。

 

针对 10gR2 及之后版本,我们虽然不能直接取得密码,但也可以通过更新内部表的方式来实现迁移。Oracle 对于直接修改内部表是严格禁止的,因为不当操作可能会造成数据库宕机、甚至永久性损坏。因为 dblink 是数据库里比较独立关联性小的一个功能,因此我们才有可能采取这种方式。但即便如此,也要求在做好备份后,由经验丰富掌握相关知识的工程师进行操作。

 

同样,先来看看数据库版本:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第10张图片


数据库链接


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第11张图片

还是以数据库链接 source 为例,我们先测试其可用性:



接下来我们看看 sys.link$ 在 10gR2 及之后的表结构变化,并直接从其中查询密码:


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第12张图片

与上面的9i对比,多了两个列,其中 PASSWORDX 列就是用来存储加密之后的密码。


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第13张图片

通过查询我们发现,password 列虽然还在,但是内容为空,passwordx 列则保存了加密之后的密码。

 

我们可以通过 pl/sql dev 之类的工具,将 sys.link$ 的内容导出为 sql 语句,每个 insert 语句对应一个 dblink 信息。对导出文件进行编辑,保留我们需要迁移的 dblink 语句,删掉其它。


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第14张图片


在目标环境上以 sys 身份执行脚本,然后对迁移后的 dblink 进行测试。


Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第15张图片

Oracle 实用技巧之不知道密码情况下 dblink 的迁移_第16张图片


至此,完成了在不知道密码情况下对 dblink 的迁移。另外,这里再插入个小知识点:还有另外的技巧能够简单快速的实现这个事情,使用 dbms_metadata 包,抽取 dblink 的 ddl,会生成包含加密密码的创建语句,在目标库跑这个 ddl,也能实现创建。但是这个方法,在11.2.0.4版本及以后被 Oracle 禁用了,不再支持。所以这里就不演示啦。那个 ddl 抽取出来的样子,基本是这样:



因为是用加密字符串表达密码,所以比平时多了个 values 关键字。


最后,再谈谈本文的编写思想,其实就是盖老师推崇的学习方法:“由点及面,穷就根本”。


当遇到一个问题后,一定是深入下去,穷究根本,这样你会发现,一个简单的问题也必定会带起一大片的知识点,如果你能对很多问题进行深入思考和研究,那么在深处,你会发现,这些面逐渐接合,慢慢的延伸到 Oracle 的所有层面,逐渐的你就能融会贯通。这时候,你会主动的去尝试全面学习 Oracle,扫除你的知识盲点,学习已经成为一种需要。由实践触发的学习才最有针对性,才更能让你深入的理解书本上的知识,正所谓:"纸上得来终觉浅,绝知此事要躬行",实践的经验于我们是至为宝贵的。与同学们共勉

你可能感兴趣的:(Oracle,Database)