共計(jì) 4352 個(gè)字符,預(yù)計(jì)需要花費(fèi) 11 分鐘才能閱讀完成。
這篇文章給大家分享的是有關(guān)使用 DBLink 過程中遇到的問題有哪些的內(nèi)容。丸趣 TV 小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨丸趣 TV 小編過來看看吧。
1. 創(chuàng)建 DBLink
1.1 創(chuàng)建命令
create database link zlbak
connect to zlbak01 identified by his using orcl
注意,引號里的 orcl,是在數(shù)據(jù)庫服務(wù)器配置好的服務(wù)名,不是客戶端本機(jī)配置的。
1.2 名稱
如果參數(shù) global_names 為 True,則要求創(chuàng)建的 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
可以通過下面的命令將名稱改短,去掉點(diǎn)后面的字符。
update global_name set
global_name = orcl
注意,千萬不能改為空,否則會造成數(shù)據(jù)庫無法啟動(dòng),需要用特殊的方法才能解決。
如果通過下面這種方法修改,之前有域名的話,修改后仍然會有點(diǎn)后名的域名。
alter
database rename global_name to orcl
當(dāng) global_names 為 True 時(shí),如果要建多個(gè) DBLink 指向同一個(gè)庫,不能重名,怎么辦呢?
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 后面加上 @再加上一個(gè)標(biāo)識。
既然 global_names 為 True 時(shí)這么麻煩,是否可以改為 false 呢?
如果不用流復(fù)制的話,完全是可以的,修改方法:
alter system set
global_name=false;
修改后重新啟動(dòng)數(shù)據(jù)庫設(shè)置才能生效,改成 false 之后,DBLink 的名稱就可以隨意取了。
1.3 特殊案例
記得是在 2014 年,做第一家用戶的歷史數(shù)據(jù)轉(zhuǎn)出,完成之后,準(zhǔn)備通過 DBLink 來實(shí)現(xiàn)遠(yuǎn)程歷史庫的查詢,遇到一個(gè)奇怪的問題。
通過下面的命令創(chuàng)建的 DBLink:
create database link
zlbak connect to zlbak01 identified by his using orcl
注意,引號里的 orcl,是在數(shù)據(jù)庫服務(wù)器配置好的服務(wù)名,不是客戶端本機(jī)配置的。
創(chuàng)建好之后,無法正常使用,執(zhí)行查詢報(bào)錯(cuò):
select * from 人員表 @zlbak
ORA-12543:TNS:無法連接目標(biāo)主機(jī)。
在服務(wù)器上,用 tnsping 服務(wù)名 orcl 是通的。
在 sqlplus 中通過 zlbak01 用戶連接 orcl 也可以正常登錄。
用戶環(huán)境是 10.2.0.5 windows 64bit。
弄了一個(gè)晚上,最后改成下面這種方式才成功了。
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 查詢遠(yuǎn)程數(shù)據(jù)
2.1 不支持查詢含有 LOB 類型字段的遠(yuǎn)程表
當(dāng)遠(yuǎn)程表含有 blob,clob,xmltype,long 等大數(shù)據(jù)類型字段時(shí),通過 DBLink 查詢會報(bào)錯(cuò):
ORA-22992: 無法使用從遠(yuǎn)程表選擇的 LOB 定位器
目前已知的兩種做法:
a. 對象表加函數(shù)轉(zhuǎn)換
源端
1)
創(chuàng)建 OBJECT 類型,字段跟原表相同,只是把 LOB 字段改為 Varchar2(4000)
2)
以該類型再創(chuàng)建一個(gè) Table 類型
3)
創(chuàng)建一個(gè)讀取轉(zhuǎn)換函數(shù),將原表的數(shù)據(jù),插入到 Table 類型中并返回
以游標(biāo)循環(huán)方式,用 dbms_lob.getlength 和 dbms_lob.substr,每次最多取 4000 個(gè)字符,用 Pipe
Row 管道函數(shù)輸出,需要用自治事務(wù),函數(shù)返回前提交事務(wù)。
4)
創(chuàng)建一個(gè)視圖,調(diào)用該函數(shù),并以 Table 語句轉(zhuǎn)換為二維表。
目標(biāo)端
1)
定義與源端相同的 OBJECT 類型和 Table 類型
2)
創(chuàng)建一個(gè)接收轉(zhuǎn)換函數(shù),把從源端接收到的 Varchar2(4000) 拼接后轉(zhuǎn)換為 LOB 類型。
需要用到自治事務(wù)
3)
創(chuàng)建一個(gè)視圖,通過 DBLink 查詢數(shù)據(jù),通過上一步創(chuàng)建的函數(shù)轉(zhuǎn)換為 LOB 字段。
4)
查詢這個(gè)視圖,就像查詢表的數(shù)據(jù)一樣,可以正常返回 LOB 字段數(shù)據(jù)。
這種方法雖然能夠?qū)崿F(xiàn),但是由于視圖加函數(shù)方式,無法利用索引,所以,只能做為臨時(shí)性的查詢手段,并且實(shí)現(xiàn)起來比較麻煩。
b. 臨時(shí)表
雖然不支持直接通過 DBLink 方式查詢 LOB 類型的字段,但是 insert
into ……Select 方式是支持的。所以,可以在本地服務(wù)器創(chuàng)建一個(gè)臨時(shí)表,將查詢的遠(yuǎn)程數(shù)據(jù)表的數(shù)據(jù)插入到臨時(shí)表,然后,通過臨時(shí)表就可以正常訪問到含有 LOB 類型字段的表了。
這種方式實(shí)現(xiàn)起來比“對象表加轉(zhuǎn)換函數(shù)”簡單得多,重要的是可以用到索引。
2.2 通過 driving_site 來指定驅(qū)動(dòng)表
很多技術(shù)人員在用戶環(huán)境中,通過 DBLink 來關(guān)聯(lián)查詢一些業(yè)務(wù)系統(tǒng)的遠(yuǎn)程數(shù)據(jù)表,但是,可能大多數(shù)人并沒有注意到一個(gè)問題:遠(yuǎn)程數(shù)據(jù)表的全表復(fù)制。
你可能以為它會像本地表一樣用到索引,實(shí)際上,很可能根本就沒有用到索引,不信你可以馬上看看那些 SQL 的執(zhí)行計(jì)劃,注意分析其中操作為 Remote 的行,那就是全表復(fù)制。
訪問遠(yuǎn)程數(shù)據(jù)表時(shí),如果在索引相關(guān)字段的查詢條件中直接指定了值,則可以直接利用索引。
例如:
Select id from H 病人醫(yī)囑記錄 where 病人 id=:v1;
其中”H 病人醫(yī)囑記錄”是一個(gè)通過 DBLink 連接到遠(yuǎn)程數(shù)據(jù)庫表的視圖。
但是,以下幾種常見情況,是沒有利用遠(yuǎn)程表的索引的:
1)
本地表和遠(yuǎn)程表的連接
2)
Table 內(nèi)存表和遠(yuǎn)程表的連接
3)
索引相關(guān)的查詢條件用到了 Or
例如:
Select b.Id, b. 類別, c. 名稱 As 類別名稱, b. 名稱, b. 標(biāo)本部位
From H 病人醫(yī)囑記錄 A, 診療項(xiàng)目目錄 B, 診療項(xiàng)目類別 C,
Table(f_Num2list( 43190722,
43190723 )) D
Where a.Id = d.Column_Value
And a. 診療項(xiàng)目 id
= b.Id And b. 類別 = c. 編碼
這種情況,會將遠(yuǎn)程數(shù)據(jù)表的全部數(shù)據(jù)查詢后傳輸?shù)奖镜胤?wù)器,再進(jìn)行表間連接。
當(dāng)遠(yuǎn)程表是大表,本地表是小表,關(guān)聯(lián)查詢時(shí),需要決定數(shù)據(jù)復(fù)制的方向,這是分布式數(shù)據(jù)訪問都存在的一個(gè)問題。
在 Select 后加提示字 /*+driving_site(a)*/ 這種方式可以指定遠(yuǎn)程表為驅(qū)動(dòng)表,把本地的小表復(fù)制到遠(yuǎn)程,這樣就可以用到索引了,并且避免了復(fù)制大表數(shù)據(jù)到本地服務(wù)器。
但是,如果含有 Table 內(nèi)存表這種情況,還是無法利用索引,因?yàn)閮?nèi)存表的數(shù)據(jù)不支持作為被驅(qū)動(dòng)表復(fù)制到遠(yuǎn)程,可以改寫查詢,避免使用 Table 方式。例如,用 in 方式,直接將條件值傳入,帶來的問題是無法使用綁定變量,對于歷史數(shù)據(jù)查詢這種低頻業(yè)務(wù),不使用綁定變量是可以接受的。
注意,driving_site 對 dml 無效 (insert,delete,update),dml 以目標(biāo)表所在庫驅(qū)動(dòng) SQL 計(jì)劃。
還有下面這種情況,雖然都是遠(yuǎn)程表連接,但是因?yàn)槭褂昧?Or,導(dǎo)致執(zhí)行計(jì)劃沒有使用索引,可以調(diào)整為將 Or 展開,寫成 Union All 方式。
Select Distinct b. 發(fā)送號, b. 發(fā)送人 As 人員, b. 發(fā)送時(shí)間 As 時(shí)間
From H 病人醫(yī)囑記錄 A, H 病人醫(yī)囑發(fā)送 B
Where a.Id = b. 醫(yī)囑 id And (a.Id =
43895356 Or a. 相關(guān) id = 43895356)
Order By 時(shí)間 Desc, 發(fā)送號
2.4 查詢 DBLink 后需要關(guān)閉連接
通過 db-link 執(zhí)行查詢后,當(dāng)前 session 到遠(yuǎn)程數(shù)據(jù)庫的連接是不會自動(dòng)關(guān)閉的,在基于連接池的管理中可能會引起目標(biāo)數(shù)據(jù)庫的 Session 泛濫,從而消耗進(jìn)程資源。
這種情況下,可以在查詢完成之后執(zhí)行關(guān)閉連接命令:
alter
sesssion close database link orcl;
注意需要先執(zhí)行 commit 命令。也可以使用系統(tǒng)包來關(guān)閉連接:
DBMS_SESSION.CLOSE_DATABASE_LINK(orcl);
2.5 提交事務(wù)
在使用 PL/SQL developer 里面通過 dblink 執(zhí)行查詢后,
commit 和 rollback 會亮,是什么原因呢?
下面的測試可以發(fā)現(xiàn)一些規(guī)律:
select count(1) from test@dblink;
不會產(chǎn)生 commit 提示
select * from
test@dblink;
會產(chǎn)生 commit 提示
select * from
test@dblink where rownum
不會產(chǎn)生 commit 提示
原來,當(dāng)需要的數(shù)據(jù)都返回了,就不會產(chǎn)生 commit 提示,否則就會產(chǎn)生 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 以下兩個(gè)參數(shù)可以調(diào)整打開的 DBLink 數(shù)量。
open_links : 每個(gè) session 最多允許的 dblink 數(shù)量;
open_links_per_instance: 指每個(gè)實(shí)例最多允許的 dblink 個(gè)數(shù)
當(dāng)前打開的 DBLink 可以查詢視圖 v$dblink。
3.2 通過 DBLink 插入數(shù)據(jù)到遠(yuǎn)程數(shù)據(jù)庫
含有 XMLType 等對象類型或用戶定義類型字段的表,不支持將通過 DBLink 插入到遠(yuǎn)程數(shù)據(jù)庫。
所以,直接將要轉(zhuǎn)移的歷史數(shù)據(jù)通過 DBLink 插入到遠(yuǎn)程歷史庫,有些表是不支持的。
3.3 不支持通過 DBLink 執(zhí)行 DDL 語句
這個(gè)比較可以理解,必竟修改數(shù)據(jù)結(jié)構(gòu),涉及到的關(guān)聯(lián)處理太多,例如并發(fā)控制等。
感謝各位的閱讀!關(guān)于“使用 DBLink 過程中遇到的問題有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!