使用DBLink过程中遇到的问题有哪些

65次阅读
没有评论

共计 4352 个字符,预计需要花费 11 分钟才能阅读完成。

这篇文章给大家分享的是有关使用 DBLink 过程中遇到的问题有哪些的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。

1.  创建 DBLink

1.1 创建命令

create database link zlbak
connect to zlbak01 identified by his using orcl

注意,引号里的 orcl,是在数据库服务器配置好的服务名,不是客户端本机配置的。

1.2 名称

如果参数 global_names 为 True,则要求创建的 DBLink 名称必须与被连接库的 global_name 相同。

create database link
orcl connect to zlbak01 identified by his using orcl

被连接的库,global_name 可能很长,例如:

select * from
global_name;

ORCL.REGRESS.RDBMS.DEV.US.ORACLE.COM

可以通过下面的命令将名称改短,去掉点后面的字符。

update global_name set
global_name = orcl

注意,千万不能改为空,否则会造成数据库无法启动,需要用特殊的方法才能解决。

如果通过下面这种方法修改,之前有域名的话,修改后仍然会有点后名的域名。

alter
database rename global_name to orcl

当 global_names 为 True 时,如果要建多个 DBLink 指向同一个库,不能重名,怎么办呢?

create database link
orcl@link1 connect to zlbak01 identified by his using orcl

create database link
orcl@link2 connect to zlbak01 identified by his using orcl

原来,需要在 GLOBAL_NAME 后面加上 @再加上一个标识。

既然 global_names 为 True 时这么麻烦,是否可以改为 false 呢?

如果不用流复制的话,完全是可以的,修改方法:

alter system set
global_name=false;

修改后重新启动数据库设置才能生效,改成 false 之后,DBLink 的名称就可以随意取了。

1.3 特殊案例

记得是在 2014 年,做第一家用户的历史数据转出,完成之后,准备通过 DBLink 来实现远程历史库的查询,遇到一个奇怪的问题。

通过下面的命令创建的 DBLink:

create database link
zlbak connect to zlbak01 identified by his using orcl

注意,引号里的 orcl,是在数据库服务器配置好的服务名,不是客户端本机配置的。

创建好之后,无法正常使用,执行查询报错:

select * from 人员表 @zlbak

ORA-12543:TNS:无法连接目标主机。

在服务器上,用 tnsping 服务名 orcl 是通的。

在 sqlplus 中通过 zlbak01 用户连接 orcl 也可以正常登录。

用户环境是 10.2.0.5 windows 64bit。

弄了一个晚上,最后改成下面这种方式才成功了。

create database link
zlbak connect to zlbak01 identified by his using
(DESCRIPTION = (ADDRESS_LIST=

(ADDRESS=(PROTOCOL=TCP)

(HOST=192.1.68.1.1)(PORT=1521)))

(CONNECT_DATA=(SERVICE_NAME=orcl)))

2.  通过 DBLink 查询远程数据

2.1 不支持查询含有 LOB 类型字段的远程表

当远程表含有 blob,clob,xmltype,long 等大数据类型字段时,通过 DBLink 查询会报错:

ORA-22992: 无法使用从远程表选择的 LOB 定位器

目前已知的两种做法:

a.  对象表加函数转换

源端

1) 
创建 OBJECT 类型,字段跟原表相同,只是把 LOB 字段改为 Varchar2(4000)

2) 
以该类型再创建一个 Table 类型

3) 
创建一个读取转换函数,将原表的数据,插入到 Table 类型中并返回

以游标循环方式,用 dbms_lob.getlength 和 dbms_lob.substr,每次最多取 4000 个字符,用 Pipe
Row 管道函数输出,需要用自治事务,函数返回前提交事务。

4) 
创建一个视图,调用该函数,并以 Table 语句转换为二维表。

目标端

1) 
定义与源端相同的 OBJECT 类型和 Table 类型

2) 
创建一个接收转换函数,把从源端接收到的 Varchar2(4000) 拼接后转换为 LOB 类型。

需要用到自治事务

3) 
创建一个视图,通过 DBLink 查询数据,通过上一步创建的函数转换为 LOB 字段。

4) 
查询这个视图,就像查询表的数据一样,可以正常返回 LOB 字段数据。

这种方法虽然能够实现,但是由于视图加函数方式,无法利用索引,所以,只能做为临时性的查询手段,并且实现起来比较麻烦。

b.  临时表

虽然不支持直接通过 DBLink 方式查询 LOB 类型的字段,但是 insert
into ……Select 方式是支持的。所以,可以在本地服务器创建一个临时表,将查询的远程数据表的数据插入到临时表,然后,通过临时表就可以正常访问到含有 LOB 类型字段的表了。

这种方式实现起来比“对象表加转换函数”简单得多,重要的是可以用到索引。

2.2 通过 driving_site 来指定驱动表

很多技术人员在用户环境中,通过 DBLink 来关联查询一些业务系统的远程数据表,但是,可能大多数人并没有注意到一个问题:远程数据表的全表复制。

你可能以为它会像本地表一样用到索引,实际上,很可能根本就没有用到索引,不信你可以马上看看那些 SQL 的执行计划,注意分析其中操作为 Remote 的行,那就是全表复制。

访问远程数据表时,如果在索引相关字段的查询条件中直接指定了值,则可以直接利用索引。

例如:

Select id from H 病人医嘱记录 where 病人 id=:v1;

其中”H 病人医嘱记录”是一个通过 DBLink 连接到远程数据库表的视图。

但是,以下几种常见情况,是没有利用远程表的索引的:

1) 
本地表和远程表的连接

2) 
Table 内存表和远程表的连接

3) 
索引相关的查询条件用到了 Or

例如:

Select b.Id, b. 类别, c. 名称 As 类别名称, b. 名称, b. 标本部位

From H 病人医嘱记录 A, 诊疗项目目录 B, 诊疗项目类别 C,

Table(f_Num2list( 43190722,
43190723 )) D

Where a.Id = d.Column_Value
And a. 诊疗项目 id
= b.Id And b. 类别 = c. 编码

这种情况,会将远程数据表的全部数据查询后传输到本地服务器,再进行表间连接。

当远程表是大表,本地表是小表,关联查询时,需要决定数据复制的方向,这是分布式数据访问都存在的一个问题。

在 Select 后加提示字 /*+driving_site(a)*/ 这种方式可以指定远程表为驱动表,把本地的小表复制到远程,这样就可以用到索引了,并且避免了复制大表数据到本地服务器。

但是,如果含有 Table 内存表这种情况,还是无法利用索引,因为内存表的数据不支持作为被驱动表复制到远程,可以改写查询,避免使用 Table 方式。例如,用 in 方式,直接将条件值传入,带来的问题是无法使用绑定变量,对于历史数据查询这种低频业务,不使用绑定变量是可以接受的。

注意,driving_site 对 dml 无效 (insert,delete,update),dml 以目标表所在库驱动 SQL 计划。

还有下面这种情况,虽然都是远程表连接,但是因为使用了 Or,导致执行计划没有使用索引,可以调整为将 Or 展开,写成 Union All 方式。

Select Distinct b. 发送号, b. 发送人 As 人员, b. 发送时间 As 时间

From H 病人医嘱记录 A, H 病人医嘱发送 B

Where a.Id = b. 医嘱 id And (a.Id =
43895356 Or a. 相关 id = 43895356)

Order By 时间 Desc, 发送号

2.4 查询 DBLink 后需要关闭连接

通过 db-link 执行查询后,当前 session 到远程数据库的连接是不会自动关闭的,在基于连接池的管理中可能会引起目标数据库的 Session 泛滥,从而消耗进程资源。

这种情况下,可以在查询完成之后执行关闭连接命令:

alter
sesssion close database link orcl;

注意需要先执行 commit 命令。也可以使用系统包来关闭连接:

DBMS_SESSION.CLOSE_DATABASE_LINK(orcl);

2.5 提交事务

在使用 PL/SQL developer 里面通过 dblink 执行查询后,

commit 和 rollback 会亮,是什么原因呢?

下面的测试可以发现一些规律:

select count(1) from test@dblink;

不会产生 commit 提示

select * from
test@dblink;

会产生 commit 提示

select * from
test@dblink where rownum

不会产生 commit 提示

原来,当需要的数据都返回了,就不会产生 commit 提示,否则就会产生 commit 提示。

通过下面的语句,可以查到回滚段的情况:

Select s.Sid,
s.Serial#, s.Sql_Hash_Value,

r.Segment_Name, t.Xidusn, t.Xidslot,
t.Xidsqn

From V$session S,
V$transaction T, Dba_Rollback_Segs R

Where s.Taddr = t.Addr
And t.Xidusn = r.Segment_Id(+);

3. 其他

3.1 以下两个参数可以调整打开的 DBLink 数量。

open_links : 每个 session 最多允许的 dblink 数量;

open_links_per_instance: 指每个实例最多允许的 dblink 个数

当前打开的 DBLink 可以查询视图 v$dblink。

3.2 通过 DBLink 插入数据到远程数据库

含有 XMLType 等对象类型或用户定义类型字段的表,不支持将通过 DBLink 插入到远程数据库。

所以,直接将要转移的历史数据通过 DBLink 插入到远程历史库,有些表是不支持的。

3.3 不支持通过 DBLink 执行 DDL 语句

  这个比较可以理解,必竟修改数据结构,涉及到的关联处理太多,例如并发控制等。

感谢各位的阅读!关于“使用 DBLink 过程中遇到的问题有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-24发表,共计4352字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)