Oracle dblink介紹
官網:
當用戶要跨本地數據庫訪問另外一個數據庫表中的數據時,本地數據庫中必須創建了遠程數據庫的DBLINK,通過DBLINK可以像訪問本地數據庫一樣訪問遠程數據庫表中的數據。其實,DBLINK和數據庫中的VIEW差不多,創建DBLINK的時候需要知道待讀取數據庫的IP地址、ORACLE_SID以及數據庫用戶名和密碼。
在創建DBLINK之前,普通用戶必須具有相關的權限才能創建DBLINK,以SYS用戶登錄到本地數據庫可以看到相關的權限:
SELECT * FROM USER_SYS_PRIVS T WHERE T.PRIVILEGE LIKE UPPER('%LINK%');
SYS@PROD1> SELECT * FROM USER_SYS_PRIVS T WHERE T.PRIVILEGE LIKE UPPER('%LINK%');
USERNAME PRIVILEGE ADM
------------------------------ ---------------------------------------- ---
SYS CREATE DATABASE LINK NO
SYS DROP PUBLIC DATABASE LINK NO
SYS CREATE PUBLIC DATABASE LINK NO
可以看出,在數據庫中DBLINK有3種權限:CREATE DATABASE LINK(所創建的DBLINK只能是創建者自己使用,別的用戶不能使用)、CREATE PUBLIC DATABASE LINK(PUBLIC表示所創建的DBLINK所有用戶都可以使用)與DROP PUBLIC DATABASE LINK(刪除公共的DBLINK)。可以使用如下授權語句給用戶SCOTT授予CREATE PUBLIC DATABASE LINK和DROP PUBLIC DATABASE LINK兩個權限:
GRANT CREATE PUBLIC DATABASE LINK,DROP PUBLIC DATABASE LINK TO SCOTT;
查詢數據庫的DBLINK可以使用SQL語句:SELECT * FROM DBA_DB_LINKS。
創建DBLINK一般有兩種方式,第一種方式是在本地數據庫tnsnames.ora文件中配置了要遠程訪問的數據庫的TNS,例如這里配置了TNS_BJLHR,然后創建公共DBLINK:
CREATE PUBLIC DATABASE LINK
DBL_BJLHR CONNECT TO SCOTT IDENTIFIED BY TIGER USING 'TNS_BJLHR';
其中,DBL_BJLHR是創建的DBLINK名字,SCOTT/TIGER是登錄到遠程數據庫的用戶名/密碼,然后在本地數據庫中通過DBLINK訪問遠程數據庫“TNS_BJLHR”中SCOTT.TB_TEST表,SQL語句如下所示:
SELECT * FROM SCOTT.TB_TEST@DBL_BJLHR;
創建DBLINK的第二種方式,是在本地數據庫tnsnames.ora文件中沒有配置要訪問的遠程數據庫的時候,而直接將相關的內容寫到DBLINK的配置中,如下所示:
CREATE DATABASE LINK DBL_BJLHR
CONNECT TO SCOTT IDENTIFIED BY TIGER
USING '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.10)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = BJLHR)
)
)';
其中,HOST為數據庫的IP地址,SERVICE_NAME為數據庫的SID,其實,兩種方法配置DBLINK是差不多的,第二種方法不受本地服務的影響。
另外,當數據庫參數GLOBAL_NAMES為TRUE時,要求數據庫鏈接名稱跟遠端數據庫名稱一樣。數據庫全局名稱可以用以下命令查出:
SELECT * FROM GLOBAL_NAME;
用以下語句來修改參數值:
ALTER SYSTEM SET GLOBAL_NAMES=FALSE/TRUE;
當數據庫參數GLOBAL_NAMES為FALSE時,就不要求數據庫鏈接名稱跟遠端數據庫名稱一樣。
11.4.2 一道OCM考題
1. Create DBLINK
1.1 Create DBLINK, should query on the PROD2 database all the table under the system user in the PROD1 Database.
1. Create Synonym
1.1 Create a sh.sales@PROD1 on the public synonyms in the PROD2, requires that all users can access.
題目要求在PROD2數據庫上可以查詢PROD1數據庫上system用戶下的所有表,並且在prod2上創建一個sh.sales@PROD1的同義詞:
create public database link PROD1 connect to system identified by oracle using 'PROD1';
create public synonym sy_ss for sh.sales@PROD1;
1、概念:database link是定義一個數據庫到另一個數據庫的路徑的對象,database link
允許你查詢遠程表及執行遠程程序。
2、建立database link之前需要確認的事項:
確認從local database到remote database的網絡連接是正常的,tnsping要能成功。
確認在remote database上面有相應的訪問權限。
3、database link分類:
類型 |
Owner |
描述 |
Private |
創建database link的user擁有該database link |
在本地數據庫的特定的schema下建立的database link。只有建立該database link的schema的session能使用這個database link來訪問遠程的數據庫。同時也只有Owner能刪除它自己的private database link。 |
Public |
Owner是PUBLIC. |
Public的database link是數據庫級的,本地數據庫中所有的擁有數據庫訪問權限的用戶或pl/sql程序都能使用此database link來訪問相應的遠程數據庫。 |
Global |
Owner是PUBLIC. |
Global的database link是網絡級的,When an Oracle network uses a directory server, the directory server automatically create and manages global database links (as net service names) for every Oracle Database in the network. Users and PL/SQL subprograms in any database can use a global link to access objects in the corresponding remote database. Note: In earlier releases of Oracle Database, a global database link referred to a database link that was registered with an Oracle Names server. The use of an Oracle Names server has been deprecated. In this document, global database links refer to the use of net service names from the directory server. |
4、創建dblink所需的權限
Privilege |
Database |
Required For |
CREATE DATABASE LINK |
Local |
Creation of a private database link. |
CREATE PUBLIC DATABASE LINK |
Local |
Creation of a public database link. |
CREATE SESSION |
Remote |
Creation of any type of database link. |
1、如果需要創建全局 DBLink,則需要先確定用戶有創建 dblink 的權限:
- select * from user_sys_privs where privilege like upper('%DATABASE LINK%');
如果沒有,則需要使用 sysdba 角色給用戶賦權:
- grant create public database link to dbusername;
2、使用該用戶登錄 PL/SQL,使用命令:
- -- 第一種方法:要求數據庫服務器 A 上 tnsnames.ora 中有 數據庫 B 的映射
- -- -- create database link 數據庫鏈接名 connect to 用戶名 identified by 密碼 using '本地配置的數據的實例名';
采用圖形配置界面則如下所示:
- -- 第二種方法:直接配置
- -- 如果創建全局 dblink,必須使用 systm 或 sys 用戶,在 database 前加 public。
- create /* public */ database link dblink1
- connect to dbusername identified by dbpassword
- using '(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = orcl)))';
- -- 數據庫參數 global_name=true 時要求數據庫鏈接名稱跟遠端數據庫名稱一樣。數據庫全局名稱可以用以下命令查出
- -- select * from global_name;
3、查詢數據:
- -- 查詢、刪除和插入數據和操作本地的數據庫是一樣的,只不過表名需要寫成“表名@dblink服務器”而已。
- select xxx FROM 表名@數據庫鏈接名;
4、刪除 DBLink
- drop /* public */ database link dblink1;
5、創建和刪除同義詞
- create or replace synonym 同義詞名 for 表名;
- create or replace synonym 同義詞名 for 用戶.表名;
- create or replace synonym 同義詞名 for 表名@數據庫鏈接名;
- drop synonym 同義詞名;
6、創建和刪除視圖
- create or replace view 視圖名 as (select 字段 from 用戶.表名@dblink1);
- drop view 視圖名;
7、注意:
創建 DBLink 很簡單,但是在使用中后台卻出現鎖,查看這個鎖的方法可以去 console 中看到或者查詢數據庫。每次使用dblink查詢的時候,均會與遠程數據庫創建一個連接,dblink 應該不會自動釋放這個連接,如果是大量使用 dblink 查詢,會造成 web 項目的連接數不夠,導致系統無法正常運行,導致系統無正常運行。
Oracle DBLINK
作用:將多個不同地點的服務器的oracle數據庫邏輯上看成一個數據庫,也就是說在一個數據庫中可以操作另一個遠程的數據庫中的對象。
語法:
CREATE [PUBLIC] DATABASE LINK dblink CONNECT TO user IDENTIFIED BY password USING ‘connect_string’;
DROP [PUBLIC] DATABASE LINK dblink;
注意:你必須有CREATE DATABASE LINK或CREATE PUBLIC DATABASE LINK的權限(可用sys身份去分配),另外,在你要連接的數據庫上的權限.
grant CREATE DATABASE LINK to hr;
參數說明:
dblink: 你所創建的database link的名字,
user和password:要連接的數據庫的用戶名和密碼
connect_string:可以是經過Net Manager配置的(tnsnames.ora)且經測試可以連接的服務名,不過也更直接用tnsnames里的字符串:(DESCRIPTION =
(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = even.oracle.com)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME =orcl) )
通過SHOW PARAMETER GLOBAL_NAMES,可以查看到其值是FALSE或者TRUE。
一)對於GLOBAL_NAMES=FALSE的情況,則DBLINK的名稱可以自定義,相關的過程如下:
實現從本地數據庫連接到遠端數據庫服務器:
遠程服務器要配置監聽並且啟動它
本地服務器要配置tnsnames
實現在本地服務器上連接到遠程服務器數據庫:
在本地數據庫上,創建連接:
1、 鏈接字符串即服務名,首先在本地配置一個服務名,地址指向遠程的數據庫地址,當然也直接寫的連接字符串。
2、創建數據庫鏈接(前提是已分配相應權限),
SQL> grant CREATE DATABASE LINK to hr;
Grant succeeded.
SQL> CREATE DATABASE LINK LinkRemoteTestDB CONNECT TO hr IDENTIFIED BY hr USING 'test';
Database link created.
當然也可以直接寫連接字符串
SQL>create database link LinkRemoteTestDB2 connect to hr identified by hr
using 'TEST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = even.oracle.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = test)
)
)';
則創建了一個以hr用戶和TEST數據庫的鏈接LinkRemoteTestDB.
3.使用database link來查詢遠程HR schema下的testdblink 表信息
SQL> select * from ;
ID NAME
---------- ----------------------------------------
1 Watson
2 John
通過執行select * from ; 進行測試,結果OK
二)對於GLOBAL_NAMES = TRUE的情況,數據庫鏈接(DATABASE LINK)的名字必須和數據庫的名字相同:
在本地服務器上執行下面語句使GLOBAL_NAMES=TRUE:
SQL>ALTER SYSTEM SET GLOBAL_NAMES=TRUE;
再查詢時,會有如下的錯誤:
SQL> select * from ;
select * from
*
ERROR at line 1:
ORA-02085: database link LINKREMOTETESTDB.REGRESS.RDBMS.DEV.US.ORACLE.COM
connects to TEST.REGRESS.RDBMS.DEV.US.ORACLE.COM
登錄遠端數據庫,通過執行
SQL>SELECT * FROM GLOBAL_NAME;得到其數據庫全名為TEST.REGRESS.RDBMS.DEV.US.ORACLE.COM
用原方式SQL> CREATE DATABASE LINK LinkRemoteTestDB CONNECT TO hr IDENTIFIED BY hr USING 'test';創建過程不會出錯,但執行“select * from
;”的時候,就會出現ORA-02085: database link LINKREMOTETESTDB.REGRESS.RDBMS.DEV.US.ORACLE.COM
connects to TEST.REGRESS.RDBMS.DEV.US.ORACLE.COM的錯誤了
所以需要采用下面的方式創建DBLINK:
SQL> create database link TEST.REGRESS.RDBMS.DEV.US.ORACLE.COM connect to HR identified by HR using 'TEST';
Database link created.再次執行
SQL> select * from ;
ID NAME
---------- ----------------------------------------
1 Watson
2 John
SQL> UPDATE t set t.name='WatsonModified' where id=1;
1 row updated.
SQL> select * from ;
ID NAME
---------- ----------------------------------------
1 WatsonModified
2 John
執行成功了!!!!!
DBLINK其他相關的知識:
1、查看所有的數據庫鏈接
SQL>select owner,object_name from dba_objects where object_type='DATABASE LINK';
SQL>select * from dba_db_links;
2、刪除數據庫連接
SQL> drop database link LinkRemoteTestDB;
Database link dropped.
database link的使用
基本語法
CREATE [SHARED][PUBLIC] database link link_name
[CONNECT TO [user][current_user] IDENTIFIED BY password]
[AUTHENTICATED BY user IDENTIFIED BY password]
[USING 'connect_string']
說明:
1) 權限:創建數據庫鏈接的帳號必須有CREATE DATABASE LINK或CREATE PUBLIC DATABASE LINK的系統權限,用來登錄到遠程數據庫的帳號必須有CREATE SESSION權限。這兩種權限都包含在CONNECT角色中(CREATE PUBLIC DATABASE LINK權限在DBA中)。一個公用數據庫鏈接對於數據庫中的所有用戶都是可用的,而一個私有鏈接僅對創建它的用戶可用。由一個用戶給另外一個用戶授權私 有數據庫鏈接是不可能的,一個數據庫鏈接要么是公用的,要么是私有的。
2)link : 當source端的數據庫GLOBAL_NAME=TRUE時,link名必須與遠程數據庫的全局數據庫名global_name)相同;否則,可以任意命名。
3)current_user使用該選項是為了創建global類型的dblink。在分布式體系中存在多個數據庫的話。如果想要在每一個數據庫中都可以使用同樣的名字來訪問數據庫a,那在每個數據庫中都要創建一個到數據庫a的db_link,太麻煩了。所以現在有這個選項。你只要創建一次。所有的數據庫都可以使用這個db_link來訪問了。要使用這個特性,必須有oracle nameserver或者ORACLE目錄服務器。並且數據庫a的參數global_names=true.具體我也沒有創建過,沒有這個環境。
4)connectstring:連接字符串,tnsnames.ora中定義遠程數據庫的連接串,也可以在創建dblink的時候直接指定。
5)username、password:遠程數據庫的用戶名,口令。如果不指定,則使用當前的用戶名和口令登錄到遠程數據庫,當創建connected user類型的dblink時,需要如果采用數據字典驗證,則需要兩邊數據庫的用戶名密碼一致。
創建database link選項說明
取值說明
不指定 | 默認值建立一個dedicated的連接,每一個使用database link的本地session都會對應有一個遠程數據庫的session。 |
SHARED | 創建一個共享的數據庫連接,同時要指定database link_authentication。 使用shared方式的 database link是數據庫會限制到遠程數據庫的連接的數量,這樣以避免過多的連接對遠程數據庫造成太大的壓力。在使用shared database link的時候,到database link的連接會在連接以后與本地連接斷開,為防止未授權的session使用此鏈接而要求在創建shared database link的時候必須要指定database link_authentication。 (from Oracle document: A shared database link is a link between a local server process and the remote database. The link is shared because multiple client processes can use the same link simultaneously.) |
共享鏈接更多資料
共享數據庫鏈接是指該鏈接的多個用戶可以共享同一個底層網絡連接。例如,在有四位用戶的MTS(多線程服務器)環境下,每一個共享服務器進程都將與遠程服務器有一個物理鏈接,這四位用戶共享這兩個鏈接。
表面上,共享鏈接乍一聽起來像是一件好事。在某些環境下的確如此,但是,當你考慮使用共享鏈接時,應當意識到這有許多局限性和警告:
如果你使用一個專用的服務器連接來連接到你的本地數據庫,鏈接只能在你從那些連接中創建的多重會話間共享 。在MTS環境里,每一個共享服務器進程潛在地打開一個鏈接。所有的會話被同一共享服務器進程提供並且分享被那個進程打開的任意共享鏈接。因為在MTS環境里的一個共享服務器進程能夠服務於許多用戶連接,共享鏈接的使用可能導致打開的鏈接遠多於所必須的鏈接。用SHARED關鍵字建立共享數據庫鏈接。還必須使用AUTHENTICATED BY 子句在遠程系統上指定一有效的用戶名和口令。如下命令建立一個共享的、公用的、連接用戶數據庫鏈接:
CREATE SHARED PUBLIC database link GNIS
AUTHENTICATED BY DUMMY_USER IDENTIFIED BY SECRET
USING ‘GNIS’;
要獲得創建鏈接和管理分布式系統的更多資料,請查閱Oracle Technology Network ()。
使用AUTHENTICATED BY子句稍微有些困擾,但是由於實現共享鏈接的方式安全性決定它是必須的。這個例子中的用戶名和口令DUMMY_USER/SECRET必須在遠程系統上有效。然而,遠程系統上使用的帳戶仍就是連接用戶的帳戶。如果我以JEFF/SECRET登陸到我的本地數據庫並使用我剛建好的共享鏈接,將會發生以下一系列事件:
為了打開鏈接,Oracle使用DUMMY_USER/SECRET向遠程數據庫授權。然后,Oracle試圖使用HMAD/SECRET使我登陸到遠程數據庫。共享鏈接的主要目的是減少兩個數據庫服務器之間的底層網絡連接數量。它們最適合於MTS環境,在那你擁有大量的通過這一鏈接訪問遠程數據庫的用戶。觀念上,你想讓用戶數量超過共享服務器進程的數量。那么你可以通過為每一共享服務器進程打開一個鏈接而不是每位用戶打開一個鏈接的方法,節省資源。
database link使用方式
取值說明
不指定 | 默認值建立一個private的database link |
PUBLIC | 公共連接,這樣的連接可以被數據的所有的用戶訪問 |
database link用戶驗證方法 取值說明
不指定 | 默認值采取Connected User的驗證方法 |
CONNECT TO CURRENT_USER | 采取CURRENT_USER的驗證方式 |
CONNECT TO user_name IDENTIFIED BY password | 采取Fiexed User的驗證方式 |
database link創建舉例
SQL StatementConnects To DatabaseConnects AsLink Type
CREATE database link sales.us.americas.acme_auto.com USING ‘sales_us’; |
sales using net service name sales_us | Connected user | Private connected user |
CREATE database link foo CONNECT TO CURRENT_USER USING ‘am_sls’; |
sales using service name am_sls | Current global user | Private current user |
CREATE database link sales.us.americas.acme_auto.com CONNECT TO scott IDENTIFIED BY tiger USING ‘sales_us’; |
sales using net service name sales_us | scott using password tiger | Private fixed user |
CREATE PUBLIC database link sales CONNECT TO scott IDENTIFIED BY tiger USING ‘rev’; |
sales using net service name rev | scott using password tiger | Public fixed user |
CREATE SHARED PUBLIC database link sales.us.americas.acme_auto.com CONNECT TO scott IDENTIFIED BY tiger AUTHENTICATED BY anupam IDENTIFIED BY bhide USING ‘sales’; |
sales using net service name sales | scott using password tiger, authenticated as anupam using password bhide | Shared public fixed user |
不使用TNS Name一例:
CREATE database link link_name
CONNECT TO user IDENTIFIED BY screct
USING '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = sales.company.com)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = sales)
)
)';
database link的使用
-- 最簡單的用法
SELECT * FROM table_name@database link;
-- 不想讓使用的人知道database link的名字的時候
-- 建一個別名包裝一下
CREATE SYNONYM table_name FOR table_name@database link;
SELECT * FROM table_name;
-- 或者,也可以建立一個視圖來封裝
CREATE VIEW table_name AS SELECT * FROM table_name@database link;
database link刪除
-- 刪除public類型的database link
DROP PUBLIC database link link_name;
-- 刪除非public類型的database link
-- 注意:只有owner自己能刪除自己的非public類型database link
DROP database link link_name;
查看database link的信息
查看系統database link的基本信息
DBA_DB_LINKS (ALL_DB_LINKS/USER_DB_LINKS)
DBA_DB_LINKS視圖為每一定義的鏈接返回一行。OWNER 列和DB_LINK列分別顯示了這一鏈接的所有者及名稱。對公用數據庫鏈接,OWNER列將包含’PUBLIC’。如果你建立固定用戶鏈接,用戶名應在DBA_DB_LINKS視圖的USERNAME列里。ALL_DB_LINKS 視圖和 USER_DB_LINKS視圖與 DBA_DB_LINKS視圖相類似-它們分別顯示了你能夠訪問的所有鏈接及你所擁有的全部鏈接。
COL OWNER FOR A15
COL DB_LINK FOR A25
COL HOST FOR A25
COL USERNAME FOR A15
SELECT * FROM DBA_DB_LINKS;
DBA_OBJECTS (ALL_OBJECTS/USER_OBJECTS)
在這個視圖里面只能查詢到系統有那些database link以及他們的owner,創建時間等信息。
COL OWNER FOR A15
COL OBJECT_NAME FOR A25
COL OBJECT_TYPE FOR A25
SELECT OWNER,OBJECT_NAME,OBJECT_TYPE FROM DBA_OBJECTS WHERE OBJECT_TYPE LIKE 'database link';
查看保存的Fixed user database link所保存的用戶密碼,該密碼是經過加密的。
這是比較危險的一件事,有必要對表sys.link$的權限進行限制。
col host for a15
col userid for a15
col passwordx for a40
col name for a20
select name, host, userid, passwordx from sys.link$;
通過database link去SELECT遠程數據庫的一個表也是一個事務嗎?
select * from v$transaction;
-- 沒有記錄,說明沒有事務
-- 通過database link連接遠程數據庫,select 其中一個表
select * from bbs_news@mylink
select * from v$transaction;
-- 發現有一條記錄。
解釋
因為本地數據庫只是將對應的sql發送給遠程數據庫執行,接受remote db返回的結果,但他並不知道是否該sql修改了數據; 所以需要為select 語句也標示一個事務。
具體可以參考otn 分布式數據庫手冊,所以在用database link遠程訪問時,要加上set transaction read only;
close database link
ALTER SESSION CLOSE database link sales;
其實,dblink的相應屬性對應了Oracle的數據字典link$,任何針對dblink的操作都是操作該數據字典。在9i的時候,如果Oracle的global_name僅包括db_name,也就是說DB_DOMAIN的值為空。那么這個時候建立的數據庫鏈,在數據庫修改全局名GLOBAL_NAME之后(修改為db_name.db_domain格式),會無法刪除。
如果要產生數據庫鏈,必須將GLOBAL_NAME改回DB_NAME格式,即去掉后面的DOMAIN,但是這個時候,RENAME操作會自動添加域名,使得Oracle全局名無法恢復到初始狀態。因此在這情況下,如果需要刪除dblink,只能直接操作link$數據字典
delete from link$ where owner#=user_id and name=dblink_name
當然直接操作數據字典是危險的,最好做好備份,然后再進行操作。
利用dblink執行ddl
我們知道任何ddl語句都無法在dblink中直接執行,示例如下
SQL> desc db_test;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER(38)
SQL> drop table db_test@DBLINK_CONNECTED_HR;
drop table db_test@DBLINK_CONNECTED_HR
*
ERROR at line 1:
ORA-02021: DDL operations are not allowed on a remote database
通過創建存儲過程,使得能在dblink中執行ddl語句。 注意需在目標數據庫的相應用戶下創建存儲過程 ,具體如下
SQL> exec dbms_utility.EXEC_DDL_STATEMENT@dblink('drop table db_test')
PL/SQL procedure successfully completed.
SQL> desc db_test;
ERROR:
ORA-04043: object db_test does not exist
dblink的限制
You cannot perform the following operations using database links:
Grant privileges on remote objects
Execute DESCRIBE operations on some remote objects. The following remote objects, however, do support DESCRIBE operations:
Tables
Views
Procedures
Functions
Analyze remote objects
Define or enforce referential integrity
Grant roles to users in a remote database
Obtain nondefault roles on a remote database. For example, if jane connects to the local database and executes a stored procedure that uses a fixed user link connecting as scott, jane receives scott's default roles on the remote database. Jane cannot issue SET ROLE to obtain a nondefault role.
Execute hash query joins that use shared server connections
Use a current user link without authentication through SSL, password, or NT native authentication
ORA-02024: database link not found
刪除database link 時發現報錯 : ORA-02024: database link not found
1. 確認database link是否public database link ,如果是,不必是這個dblink的owner, 有
足夠的權限即可刪除 。
2. 如果是private database link,那么需要owner來刪除,否則會報錯。
3. 創建前后更改了global_name ,原來global_name=true, 創建dblink后被更改為了false .
這種情況下即使再更改回來也不能正常刪除dblink。詳見:
Cannot drop a database link after changing the global_name ORA-02024 (文檔 ID 382994.1)
刪除 Dblink 報錯 ORA-02024: database link not found 的解決方法
朋友說刪除DBLINK 報錯: ORA-02024: database link not found。
在Metalink上搜到了2篇與這個錯誤有關的文章:
Cannot drop a database link after changing the global_name ORA-02024 [ID 382994.1]
http://blog.csdn.net/tianlesoftware/archive/2011/01/23/6160082.aspx
ORA-02024: Database Link Not Found [ID 1058949.1]
http://blog.csdn.net/tianlesoftware/archive/2011/01/23/6160080.aspx
兩篇文章分別講到了2種情況。
一 . DBLINK所有者不一致造成
我們來演示一下這種情況。
--創建dblink
SQL> conn system/admin;
已連接。
SQL> create database link dave connect to system identified by admin using '
2 (DESCRIPTION =
3 (ADDRESS_LIST =
4 (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.6.100)(PORT = 1521))
5 )
6 (CONNECT_DATA =
7 (SERVICE_NAME = newccs)
8 )
9 )
10 ';
數據庫鏈接已創建。
DBLINK 創建這塊可以參考官網說明:
CREATE DATABASE LINK
--查看驗證dblink
SQL> select name from v$database@dave;
NAME
---------
NEWCCS
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
會話已更改。
SQL> select * from all_db_links;
OWNER DB_LINK USERNAME HOST CREATED
---------- ---------- ---------- ---------- -------------------
SYSTEM DAVE SYSTEM 2011-01-23 21:17:31
--我們用錯誤的所有者來刪除看看
SQL> drop public database link dave;
drop public database link dave
*
第 1 行出現錯誤:
ORA-02024: 未找到數據庫鏈接
--用正確的用戶來刪除
SQL> drop database link dave;
數據庫鏈接已刪除。
二. Global_name 造成
先看官網的一段說明:
If the value of the GLOBAL_NAMES initialization parameter is TRUE, then the database link must have the same name as the database to which it connects. If the value of GLOBAL_NAMES is FALSE, and if you have changed the global name of the database, then you can specify the global name.
The maximum number of database links that can be open in one session or one instance of an Oracle RAC configuration depends on the value of the OPEN_LINKS and OPEN_LINKS_PER_INSTANCE initialization parameters.
Global_names 是一個布爾值,global_names的作用是創建db link時是否強制使用遠程數據庫的global_name,如果global_names=true,則db link name必須要求是remote database的global_name,否則創建之后db link 不能連同,缺省值是false。 當global_name 為False時,如果我們修改了global_name,那么在dblink中也要相應的指定global_name. 並且當我們修改了global_name后,之前存在的我們dblink也無法刪除。
Global_name 是由db_name.db_domain構成。
有關這幾個參數的說明,參考:
DBID,SID,DB_NAME,DB_DOMAIN,INSTANCE_NAME,DB_UNIQUE_NAME,SERVICE_NAMES 及監聽參數的說明
http://blog.csdn.net/tianlesoftware/archive/2010/12/20/6086066.aspx
CREATE DATABASE LINK
open_links_per_instance 和 open_links 參數說明
下面來看示例:
SQL> show parameter global_names
NAME TYPE VALUE
------------------------------------ ----------- -------
global_names boolean FALSE
SQL> select * from global_name;
GLOBAL_NAME
------------------------------
NEWCCS
SQL> create database link dave connect to system identified by admin using 'newccs';
數據庫鏈接已創建。
SQL> select * from dba_db_links;
OWNER DB_LINK USERNAME HOST CREATED
---------- ---------- ---------- ---------- -------------------
SYSTEM DAVE SYSTEM newccs 2011-01-23 21:45:41
SQL> select name from v$database@dave;
NAME
---------
NEWCCS
這里要注意一點,我這里創建的dblink 使用的是監聽名:newccs. dba_db_links表中的host顯示的是這個監聽的名字。 在第一個示例中,我創建dblink 是使用命令來寫的,那種情況下host 為空。
在上面提到,當global_names為False的情況下,如果我們修改了global_name,之前創建的dblink 在刪除的時候也會包ORA-02024的錯誤。 甚至我們把global_name 改變成原來的值,也無法刪除。 因為這種改變沒有生效。 除非我們更新props$ 表。
先來驗證global_name 修改后生效問題。
SQL> select * from global_name;
GLOBAL_NAME
----------------------------------------------------------------------------
NEWCCS
SQL> alter database rename global_name to newccs.tianlesoftware.com;
數據庫已更改。
SQL> select * from global_name;
GLOBAL_NAME
----------------------------------------------------------------------------
NEWCCS.TIANLESOFTWARE.COM
SQL> alter database rename global_name to newccs;
數據庫已更改。
SQL> select * from global_name;
GLOBAL_NAME
----------------------------------------------------------------------------
NEWCCS.TIANLESOFTWARE.COM
--這里並沒有生效。
SQL> drop database link dave;
drop database link dave
*
第 1 行出現錯誤:
ORA-02024: 未找到數據庫鏈接
從上面的操作,驗證了如果僅通過alter 命令,是無法讓global_name 還原成原來的值的。並且當global_name 發生改變后,已經存在的dblink也無法刪除。
解決這個問題的方法,就是用sys用戶來修改props$表:
SQL> update props$ set value$ = '' where name ='GLOBAL_DB_NAME';
示例:
SQL> conn / as sysdba;
已連接。
SQL> update props$ set value$ = 'NEWCCS' where name ='GLOBAL_DB_NAME';
已更新 1 行。
SQL> commit;
提交完成。
然后切換到dblink 的用戶,刪除dblink:
SQL> conn system/admin;
已連接。
SQL> drop database link dave;
數據庫鏈接已刪除。
如果還報這種錯誤,可以刷新三次shared pool, 在執行drop命令:
alter system flush SHARED_POOL;
alter system flush SHARED_POOL;
alter system flush SHARED_POOL;
如果刷新shared pool后還無法drop,那么就需要重啟DB,在刪除了。
Cannot drop a database link after changing the global_name ORA-02024 (Doc ID 382994.1)
In this Document
Symptoms |
Changes |
Cause |
Solution |
References |
APPLIES TO:
There are two solutions:
1.3.3. If step b doesn't help, you need to bounce your database and try to drop the database link.
1.3.4. Once the database link is dropped, the global_name can be changed back to the desired name containing domain part using the alter database rename global_name statement
2. The second solution consists on deleting the database link directly from sys.link$:
Reference