Oracle Database Links sind eine hervorragende Möglichkeit, um Schnittstellen zwischen zwei Oracle Datenbanken aufzubauen oder Daten mit Hilfe von Materialized Views zwischen Datenbanken zu replizieren. Davon wird in Unternehmen mit verteilten Anwendung und verteilter Datenhaltung häufig Gebrauch gemacht. In diesem Artikel werde ich einen Überblick über die unterschiedlichen Datenbanklink-Typen geben und einige nützliche SQL-Abfragen präsentieren, mit denen man sich ein genaues Bild machen kann welche Database Links in einer Datenbank vorhanden sind und wie diese genutzt werden.

Oracle Database Link
Ein Oracle Database Link ist ein Objekt in der Datenbank, welches eine unidirektionale Verbindung zu einer anderen Oracle Datenbank ermöglicht. Die Definition des Database Links enthält mindestens den Namen des Database Links, des Eigentümers und Verbindungsinformationen zum Ziels. Je nach Typ, ist auch der Name und das Passwort des Users abgespeichert, zu dem eine Verbindung hergestellt werden soll. Die Information zum Ziel (Net Service Namen) wird üblicherweise als TNS-Aliasnamen angegeben, der dann in der SQL*Net Konfigurationsdatei tnsnames.ora in einen vollständigen Connect-String zur Zieldatenbank aufgelöst wird. Alternativ kann man aber auch den Connect-String selber im „Easy Connect“-Format bei der Erstellung des Database Links nutzen, um sich unabhängig von einer tnsnames.ora zu machen.
Der große Vorteil von Database Links ist, dass er Benutzern erlaubt auf Objekte anderer User in einer entfernten Datenbank mit den Privilegien der Objekteigentümers zuzugreifen. Mit anderen Worten, ein lokaler Benutzer kann auf eine entfernte Datenbank zugreifen, als wäre er der Eigentümer der Objekte in der entfernten Datenbank.
Beispiel Erstellung eines Database Links mit Tnsnames-Aliasname:
create database link <DB LINK NAME> connect to <REMOTE USER> identified by <PASSWORD> using <Tnsnames-Aliasname>;
Beispiel Erstellung eines Database Links mit Easy Connect
create database link <DB LINK NAME> connect to <REMOTE USER> identified by <PASSWORD> using '//<server>:<port>/<service_name>';
Beispiel Zugriff über einen Database Link OE_ORCL2 auf die Tabelle DEPT im Shema OE der entfernten Datenbank ORCL2
create database link oe_orcl2 connect to oe identified by mysecretpassword using '//dbserver2:1521/orcl2'; select deptno,dname from dept@oe_orcl2;
Public und Private Database Links
Ein Database Link ist üblicherweise vom Typ „Public“ oder „Private“. Es gibt noch den Typ „Global“, der einen Directory Server erfordert und für das ganze Netzwerk gilt, aber eher selten genutzt wird. Ein Database Link vom Typ Public gehört dem User Public, gilt datenbankweit und, wie bei allen Public-Objekten, steht dieser allen Benutzern und PL/SQL Programmen zur Verfügung. Daraus folgt, dass jeder Datenbankbenutzer damit auf die Objekte des definierten Users in der entfernten Datenbank zugreifen kann! Aus Sicherheitsgründen wird daher empfohlen diesen Typ nur in Ausnahmefällen zu nutzen und lieber Database Links vom Typ „Private“ zu erstellen.

Ein Database Link vom Typ Private gehört einem bestimmten User und berechtigt auch nur diesen den Database Link zu nutzen. Sprich, nur der Eigentümer des Database Links kann auf die Objekte in der entfernten Datenbank zugreifen.

Indentitäts-Typen
Bei der Erstellung eines Database Links wird anhand der Syntax festgelegt mit welcher Identität und welcher Authentifizierungsmethode sich an die entfernte Datenbank angemeldet wird. Oracle unterscheidet zwischen drei verschiedenen Kategorien.
1. Fixed-User Database Link
Dieser am häufigsten verwendete Database Link beinhaltet einen Usernamen und ein Passwort. Wenn ein solcher Database Link genutzt wird, so wird sich mit dem bei der Erstellung angegebenen Benutzer und Passwort an die entfernte Datenbank verbunden. Da dieser Datenbanklink-Typ auch das Passwort enthält, wirken sich Passwortänderungen in der entfernten Datenbank unmittelbar auf die Funktionsfähigkeit des Database Links aus. Wenn das Passwort in der entfernten Datenbank geändert wird, so muss der Database Link mit dem neuen Passwort neu erstellt werden. Ein großer Vorteil und sicher auch der Grund für die häufige Verbreitung dieses Typs ist, dass man einem Benutzer mit einfachen Mitteln Zugriff auf sämtliche Objekte eines anderen Benutzers in dessen Context erteilen kann.
Beispiel Private:
CREATE DATABASE LINK ORCL2 CONNECT TO OE IDENTIFIED BY secretpassword USING 'ORCL2';
Beispiel Public:
CREATE PUBLIC DATABASE LINK ORCL2_OE CONNECT TO OE IDENTIFIED BY secretpassword USING 'ORCL2';
2. Connected-User Database Link
Dies sind Database Links, die bezüglich des Namens und Passworts einen gleichen User in der entfernten Datenbank erfordern. Bei der Erstellung des Database Links wird kein bestimmter Usernamen oder Passwort festgelegt. Die Verbindung zur entfernten Datenbank wird mit dem User hergestellt, der den Database Link aufruft. Wenn z.B. der User SYSTEM auf einen Public Database Link zugreift, dann ist der Connected-User SYSTEM und die Verbindung wird zum Schema SYSTEM der entfernten Datenbank hergestellt. Ein Connected-User ist jeder User, der den Database Link aufrufen kann. Passwortänderungen des Nutzers müssen immer auf beiden involvierten Datenbanken identisch und zeitgleich erfolgen, um die Funktionsfähiglkeit zu erhalten.
Beispiel Private:
CREATE DATABASE LINK ORCL2_OE USING 'ORCL2';
Beispiel Public:
CREATE PUBLIC DATABASE LINK ORCL2_OE USING 'ORCL2';
3. Current-User Datenbase Link
Ein solcher Database Link erlaubt es Enterprise Users (Global Users) auf Objekte einer entfernten Datenbank zuzugreifen, ohne dass Authentifizierungsinformationen beim Aufruf des Database Links übergeben werden. Bei der Erstellung wird ebenfalls kein Usernamen und Passwort festgelegt. Voraussetzung sind SSL- oder Passwort-authentifizierte Enterprise-User, die eine entsprechend eingerichtete Infrastruktur erwarten und die in beiden involvierten Datenbanken angelegt sein müssen. Current-User Database Links dürfen aufgrund der notwendigen „Enterprise“-Authentifizierung nur mit der Oracle Advanced Security Option verwendet werden. Wenn der Aufruf des Database Links übrigens in einer Prozedur, die dem Global User gehört, erfolgt, dann muss der User, der den Database Link über die Ausführung Prozedur nutzt, nicht der Eigentümer und auch auch kein Enterprise User sein.
Beispiel Private:
CREATE DATABASE LINK ORCL2_OE CONNECT TO CURRENT_USER USING 'ORCL2';
Nützliche SQL-Abfragen zu Database Links
Folgende Abfragen helfen dem DBA Informationen zu den in einer Datenbank vorhandenen Database Links zu erhalten.
1. Anzeige der vorhandenen Database Links
set pagesize 200
set linesize 110
col "remote user" FOR a15
col "connect identifier" FOR a19
col created format a11
col owner format a15
col db_link FOR a25
SELECT owner,
db_link,
To_char(created, 'dd.mm.yyyy') created,
host "CONNECT IDENTIFIER",
username "REMOTE USER"
FROM dba_db_links
ORDER BY owner,
db_link;
OWNER DB_LINK CREATED CONNECT IDENTIFIER REMOTE USER --------------- ------------------------- ----------- ------------------- --------------- PUBLIC PH_ORCL2.EXAMPLE.DE 04.09.2007 ORCL2.EXAMPLE.DE PH HR ORCL2 04.09.2007 ORCL2.EXAMPLE.DE SCOTT PM HR_HRDB_LINK 04.05.2017 HRDB.EXAMPLE.DE HR SCOTT OE_ERPDB 27.10.2013 ERPDB OE OE SALESLINK 13.10.2016 SALESDB SH
Die gleiche Abfrage mit Information zum User-Type (Anmeldung als SYS erforderlich).
set pagesize 200
set linesize 110
col "remote user" FOR a15
col "connect identifier" FOR a19
col created format a11
col owner format a15
col db_link FOR a25
SELECT owner,
db_link,
To_char(created, 'dd.mm.yyyy') created,
host "CONNECT IDENTIFIER",
username "REMOTE USER"
FROM dba_db_links
ORDER BY owner,
db_link;
OWNER DB_LINK CREATED CONNECT IDENTIFIER REMOTE USER USER TYPE ---------- -------------------- ----------- ------------------- ------------ --------------- PUBLIC PH_ORCL2.EXAMPLE.DE 04.09.2007 ORCL2.EXAMPLE.DE PH Fixed User HR ORCL2 04.09.2007 ORCL2.EXAMPLE.DE Connected User PM HR_HRDB_LINK 04.05.2012 HRDB.EXAMPLE.DE HR Fixed User SCOTT SALESLINK 13.10.2016 SALESDB SH Fixed User OE OE_ERPDB 27.10.2013 ERPDB Connected User
2. Database Link relevante Parameter
set linesize 110
col parameter FOR a24
col value FOR a6
col isdefault FOR a9
col description FOR a61
SELECT name parameter,
display_value value,
isdefault,
description
FROM v$parameter
WHERE name IN ( 'open_links', 'open_links_per_instance', 'global_names' );
PARAMETER VALUE ISDEFAULT DESCRIPTION ------------------------ ------ --------- --------------------------------- global_names FALSE TRUE enforce that database links have same name as remote database open_links 4 TRUE max # open links per session open_links_per_instance 4 TRUE max # open links per instance
3. Nutzungs-Statistiken zu Database Links
(Seit Instancestart)
set linesize 110
col name FOR a40 head sysstat
col value FOR 9999999999999
SELECT name,
value
FROM v$sysstat
WHERE name IN ( 'bytes sent via SQL*Net to dblink',
'bytes received via SQL*Net from dblink',
'SQL*Net roundtrips to/from dblink' );
SYSSTAT VALUE ---------------------------------------- -------------- bytes sent via SQL*Net to dblink 2423247583 bytes received via SQL*Net from dblink 6705612557 SQL*Net roundtrips to/from dblink 9567350
4. Derzeit geöffnete Database Links
set pagesize 200
set linesize 110
col "db link" FOR a26
col "owner" FOR a15
col userid FOR a15 heading "remote user"
col logged_on FOR a5 heading "logon"
col protocol FOR a8
col host FOR a22 heading "connect identifier"
SELECT s.name "db link",
u.name "owner",
d.host,
userid,
logged_on
FROM v$dblink v,
sys.link$ s,
dba_db_links d,
sys.user$ u
WHERE owner# = user#
AND v.db_link = d.db_link
AND logged_on = 'YES'
ORDER BY v.db_link,
owner;
(Anmeldung als SYS erforderlich)
5. Database Links, die von Synonymen referenziert werden
set pagesize 200
set linesize 110
col synonym_owner FOR a20
col synonym_name FOR a30
col db_link FOR a40
SELECT db_link,
owner synonym_owner,
synonym_name
FROM dba_synonyms
WHERE db_link IS NOT NULL
GROUP BY db_link,
owner,
synonym_name,
db_link
ORDER BY owner,
db_link,
synonym_name;
DB_LINK SYNONYM_OWNER SYNONYM_NAME ---------------------------------------- -------------------- ------------------------------ PH_ORCL2.EXAMPLE.DE PM PH.DEPT ORCL2 SCOTT MGR.COMMENT_TXT HR_HRDB_LINK PUBLIC EMP SALESLINK PUBLIC CUSTOMER OE_ERPDB PUBLIC SALES
6. Database Links, die von MViews referenziert werden
set pagesize 200
set linesize 110
col owner FOR a20
col mview_name FOR a30
col master_link FOR a26
col refresh_mode FOR a12
col refresh_method FOR a14
SELECT master_link,
mview_name,
owner,
refresh_method
FROM dba_mviews
WHERE master_link IS NOT NULL
ORDER BY owner,
master_link;
MASTER_LINK MVIEW_NAME OWNER REFRESH_METHOD -------------------------- ------------------------------ -------------------- -------------- @PH_ORCL2.EXAMPLE.DE MV_DEVICES MGR FAST @SALESLINK MV_CUSTOMER SCOTT FAST @HR_HRDB_LINK EMP HR FAST @HR_HRDB_LINK DEPT PH FAST @OE_ERPDB RESULTS OE FAST
7. Objekte im Objekt-Cache, auf die über einen Database Link zugegriffen wird
set pagesize 200
set linesize 110
col db_link FOR a20
col name FOR a20
col owner FOR a20
col TYPE FOR a15
SELECT db_link,
owner,
name,
TYPE
FROM v$db_object_cache
WHERE db_link IS NOT NULL
ORDER BY owner,
db_link;
DB_LINK OWNER NAME TYPE -------------------- -------------------- -------------------- --------------- SALESLINK SH MAG_PCKGE PACKAGE SALESLINK SH SALES_TAB TABLE OE_ERPDB OE CALC NON-EXISTENT HR_HRDB_LINK HR V_DEPT VIEW HR_HRDB_LINK HR V_EMP_ATTRIBUTES VIEW
8. User, die aktuell ein Database Link nutzen (Incoming and Outcoming)
col origin FOR a16
col gtxid FOR a28
col lsession FOR a10
col username FOR a15
col status FOR a8
SELECT /*+ ORDERED */ Substr(s.ksusemnm, 1, 10) ||'-'|| Substr(s.ksusepid, 1, 10) "ORIGIN",
Substr(g.k2gtitid_ora, 1, 35) "GTXID",
Substr(s.indx, 1, 4)||'.'|| Substr(s.ksuseser, 1, 5)"LSESSION",
s2.username,
Substr(Decode(Bitand(ksuseidl, 11), 1, 'ACTIVE',0,Decode(Bitand(ksuseflg, 4096), 0,
'INACTIVE','CACHED'), 2, 'SNIPED', 3, 'SNIPED','KILLED'), 1, 8) "STATUS"
FROM x$k2gte g,
x$ktcxb t,
x$ksuse s,
v$session_wait w,
v$session s2
WHERE g.k2gtdxcb = t.ktcxbxba
AND g.k2gtdses = t.ktcxbses
AND s.addr = g.k2gtdses
AND w.sid = s.indx
AND s2.sid = w.sid;
(Anmeldung als SYS erforderlich)
ORIGIN GTXID LSESSION USERNAME STATUS --------------------- ---------------------------- ---------- --------------- -------- PC_SCOTT ORCL2.d90ada8a.10.29.676282 245.21421 SCOTT INACTIVE DBSERVER1 ORCL2.d90ada8a.15.25.490887 168.11363 SYS INACTIVE
9. Von Stored Objects referenzierte Database Links
set linesize 130 set pagesize 500 col object for a50 col DB_LINK for a30 head "CONTAINED DATATABASE LINK" SELECT DISTINCT s.TYPE||' '||s.owner||'.'||s.name OBJECT, l.db_link FROM dba_source s JOIN dba_db_links l ON Upper(s.text) LIKE '%@'||Upper(l.db_link)||'%' ORDER BY object;
OBJECT DATATABASE LINK ---------------------------------- ----------------------------- PACKAGE BODY PDA.DBP029 SYNC_SCOTT_OSC.WORLD PACKAGE BODY PDA.DBPCOPYSERVP SYNC_SCOTT_OSC.WORLD PACKAGE BODY PDA.DBPPLZDMAG DBSERV_DB8I PACKAGE BODY PDA.DBPPLZDMAG DBSERV_DB8I.US.ORACLE.COM PACKAGE BODY PDA.DBPPSST001 DBSERV_DB8I PACKAGE BODY PDA.DBPVFB4TOOL SYNC_SCOTT_OSC.WORLD PACKAGE BODY PDA.DBPVFB9TOOL SYNC_SCOTT_OSC.WORLD PACKAGE BODY PDA.DBPXPOBS001 XPLINK PACKAGE BODY PDA.DBPXPOBS006 XPLINK PACKAGE PDA.DBPEGK004 SYNC_SCOTT_OSC.WORLD TRIGGER PDA.PDA_ANZBUI_LOG DBSERV_DB8I
10. Von Views referenzierte Database Links
set serveroutput on
DECLARE
V_CHAR VARCHAR2(32767);
V_DBLINK_COUNT NUMBER := 0;
BEGIN
select count(*) into V_DBLINK_COUNT from dba_db_links;
IF V_DBLINK_COUNT> 0 THEN
FOR REC1 IN (select OWNER, DB_LINK DB_LINK from dba_db_links)
LOOP
FOR REC IN (SELECT owner, view_name, text FROM ALL_VIEWS WHERE TEXT_LENGTH <32767)
LOOP
V_CHAR := UPPER(REC.TEXT);
IF (INSTR(V_CHAR, '@'||REC1.DB_LINK)> 0) THEN
DBMS_OUTPUT.PUT_LINE('VIEW '||REC.OWNER||'.'||REC.VIEW_NAME||' is using '||REC1.DB_LINK);
END IF;
END LOOP;
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('No database links exists in database');
END IF;
END;
/
Einschränkung: Es werden nur Views mit maximal 32776 Zeichen berücksichtigt
VIEW PDA.Z_XPPAAUF is using DBSERV_DB8I VIEW PDA.Z_VERKBELEG is using DBSERV_DB8I VIEW PDA.ADR_EXT_AP is using DBSERV_DB8I VIEW PDA.ADR_EXT is using DBSERV_DB8I VIEW PDA.LEI_EXT is using DBSERV_DB8I VIEW PDA.Z_XPPAAUF is using DBSERV_DB8I.US.ORACLE.COM VIEW PDA.Z_VERKBELEG is using DBSERV_DB8I.US.ORACLE.COM VIEW PDA.ADR_EXT_AP is using DBSERV_DB8I.US.ORACLE.COM VIEW PDA.ADR_EXT is using DBSERV_DB8I.US.ORACLE.COM VIEW PDA.LEI_EXT is using DBSERV_DB8I.US.ORACLE.COM