温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2021-11-10 09:15:38 来源:亿速云 阅读:1004 作者:小新 栏目:关系型数据库

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

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-12543TNS:无法连接目标主机。

在服务器上,用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<5;

不会产生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过程中遇到的问题有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI