【Oracle】DBリンクの作成方法完全ガイド|CREATE DATABASE LINK・PUBLIC/PRIVATE・Easy Connect・パフォーマンス・エラー対処まで解説

【Oracle】DBリンクの作成方法完全ガイド|CREATE DATABASE LINK・PUBLIC/PRIVATE・Easy Connect・パフォーマンス・エラー対処まで解説 Oracle

Oracle のDBリンク(データベースリンク)は、あるデータベースから別のデータベースに対して SQL を実行するための接続オブジェクトです。本番とテスト環境間のデータ比較、複数拠点のデータ統合、リモートテーブルのコピーなど、複数 DB をまたぐ操作で活躍します。

本記事では、CREATE DATABASE LINK の構文から、PRIVATE / PUBLIC の違いEasy Connect 記法と tnsnames.ora の使い分けDB Link 経由の SELECT / INSERT / CTASDRIVING_SITE ヒントによるパフォーマンス最適化、そしてよくあるエラーの対処法まで体系的に解説します。

この記事でわかること
・CREATE DATABASE LINK の構文と各パラメータ
・PRIVATE リンクと PUBLIC リンクの違い
・Easy Connect 記法(tnsnames.ora 不要)での接続
・CURRENT_USER リンク(接続ユーザーの権限で実行)
・DB Link 経由の SELECT / INSERT / UPDATE / DELETE / CTAS
・シノニムで DB Link 名を隠蔽するテクニック
・DRIVING_SITE ヒントでパフォーマンスを改善する方法
・DB Link の確認・削除・クローズの管理操作
・ORA-02019 / ORA-12154 などのエラー対処
スポンサーリンク

CREATE DATABASE LINK の基本構文

SQL(基本構文)
-- 構文
CREATE [PUBLIC] DATABASE LINK link_name
CONNECT TO remote_user IDENTIFIED BY remote_password
USING 'connect_string';

-- connect_string: tnsnames.ora のエントリ名、または Easy Connect 記法
SQL(tnsnames.ora のエントリ名で接続)
-- tnsnames.ora に REMOTE_DB というエントリがある場合
CREATE DATABASE LINK remote_link
CONNECT TO app_user IDENTIFIED BY secret123
USING 'REMOTE_DB';

-- 作成後の使い方
SELECT * FROM employees@remote_link;
SQL(Easy Connect 記法: tnsnames.ora 不要)
-- Easy Connect: //host:port/service_name
CREATE DATABASE LINK remote_link
CONNECT TO app_user IDENTIFIED BY secret123
USING '//192.168.1.100:1521/ORCL';

-- ホスト名でも可
CREATE DATABASE LINK remote_link
CONNECT TO app_user IDENTIFIED BY secret123
USING '//db-server.example.com:1521/PRODDB';
Easy Connect と tnsnames.ora の使い分け
Easy Connect: tnsnames.ora の編集が不要でシンプル。テスト環境向き
tnsnames.ora: ホスト変更時に tnsnames.ora だけ修正すればよい。本番環境推奨
ネットワーク設定の詳細は「リスナー設定完全解説」を参照してください。

PRIVATE リンクと PUBLIC リンクの違い

種類 作成構文 使用できるユーザー 必要な権限
PRIVATE(デフォルト) CREATE DATABASE LINK … 作成したユーザーのみ CREATE DATABASE LINK
PUBLIC CREATE PUBLIC DATABASE LINK … 全ユーザー CREATE PUBLIC DATABASE LINK
SQL(PUBLIC リンクの作成)
-- PUBLIC リンク: 全ユーザーが使用可能
CREATE PUBLIC DATABASE LINK shared_remote
CONNECT TO app_readonly IDENTIFIED BY readonly_pw
USING '//192.168.1.100:1521/PRODDB';

-- 任意のユーザーが使用可能
SELECT * FROM orders@shared_remote;
PUBLIC リンクのセキュリティリスク
PUBLIC リンクは全ユーザーがリモート DB にアクセスできるため、権限管理が甘いと意図しないデータ漏洩につながります。本番環境ではPRIVATE リンクを推奨し、PUBLIC リンクは読み取り専用(SELECT 権限のみ)のユーザーで接続してください。

CURRENT_USER リンク(接続ユーザーの権限で実行)

SQL(CURRENT_USER リンク)
-- CONNECT TO CURRENT_USER: リモート側にも同名ユーザーが必要
CREATE DATABASE LINK remote_currentuser
CONNECT TO CURRENT_USER
USING '//192.168.1.100:1521/ORCL';

-- HR ユーザーが実行すると、リモート側の HR ユーザーの権限で接続
-- SCOTT ユーザーが実行すると、リモート側の SCOTT ユーザーの権限で接続

CURRENT_USER リンクは固定パスワードを埋め込まないため、セキュリティ面で有利です。ただし、リモート DB にも同名ユーザーが存在し、適切な権限を持っている必要があります。

DB Link 経由のデータ操作

SQL(SELECT / INSERT / UPDATE / DELETE)
-- SELECT: リモートテーブルを参照
SELECT * FROM employees@remote_link;

-- SELECT: ローカルとリモートを結合
SELECT l.order_id, r.customer_name
FROM local_orders l
JOIN customers@remote_link r ON l.customer_id = r.customer_id;

-- INSERT: リモートテーブルにデータを挿入
INSERT INTO audit_log@remote_link (action, action_date)
VALUES ('SYNC', SYSDATE);

-- UPDATE: リモートテーブルを更新
UPDATE products@remote_link
SET price = price * 1.1
WHERE category = 'FOOD';

-- DELETE: リモートテーブルから削除
DELETE FROM temp_data@remote_link WHERE created_at < SYSDATE - 30;

COMMIT;  -- リモートへの DML も COMMIT が必要
SQL(CTAS: リモートテーブルをローカルにコピー)
-- リモートのテーブル構造+データをローカルにコピー
CREATE TABLE local_employees AS
SELECT * FROM employees@remote_link;

-- 条件付きコピー
CREATE TABLE local_recent_orders AS
SELECT * FROM orders@remote_link
WHERE order_date >= DATE '2025-01-01';

テーブルコピーの詳細は「テーブルをコピーする方法」を参照してください。

シノニムで DB Link 名を隠蔽する

SQL 文に @remote_link を毎回書くのは煩雑です。シノニムを作成すれば、ローカルテーブルと同じ感覚でアクセスできます。

SQL(シノニム経由のアクセス)
-- リモートテーブルへのシノニムを作成
CREATE SYNONYM remote_employees FOR employees@remote_link;

-- @remote_link なしで使える
SELECT * FROM remote_employees;

-- PUBLIC シノニムにすれば全ユーザーが使える
CREATE PUBLIC SYNONYM remote_employees FOR employees@remote_link;
シノニムのメリット
・SQL 文から @link_name が消え、可読性が向上
・DB Link 名やリモート先が変わっても、シノニムだけ再作成すれば SQL は変更不要
・アプリケーション側にリモート接続情報を隠蔽できる

パフォーマンスの最適化

DRIVING_SITE ヒント

ローカルとリモートのテーブルを結合する分散クエリでは、どちら側で結合処理を実行するかでパフォーマンスが大きく変わります。DRIVING_SITE ヒントで処理を実行するサイトを指定できます。

SQL(DRIVING_SITE ヒント)
-- デフォルト: ローカル側で結合(リモートから全データを転送してくる)
SELECT l.order_id, r.customer_name
FROM local_orders l
JOIN customers@remote_link r ON l.customer_id = r.customer_id;

-- DRIVING_SITE でリモート側で結合を実行させる
SELECT /*+ DRIVING_SITE(r) */
    l.order_id, r.customer_name
FROM local_orders l
JOIN customers@remote_link r ON l.customer_id = r.customer_id;
-- ローカルの local_orders をリモート側に送り、リモートで結合
-- customers が大テーブルの場合に効果的
状況 推奨設定 理由
リモートテーブルが大きい DRIVING_SITE(remote_alias) リモート側で結合→結果だけ転送。大量データの転送を回避
ローカルテーブルが大きい デフォルト(ローカル側) ローカル側で結合→リモートからは必要分だけ取得
両方大きい CTAS でローカルにコピーしてから結合 分散クエリを避ける

その他のパフォーマンス注意点

注意点 対処法
リモートテーブルのフルスキャンが遅い WHERE 条件を付けてデータ転送量を削減
分散トランザクションのオーバーヘッド 読み取り専用なら分散トランザクション不要。DML は最小限に
ネットワーク遅延 DB Link 経由のループ処理を避け、一括 SQL(CTAS/INSERT SELECT)を使う
大量データの定期同期 DB Link より Data Pump(expdp/impdp)が高速

DB Link の確認・削除・クローズ

SQL(DB Link の確認)
-- 自分が作成した PRIVATE リンク
SELECT db_link, username, host, created FROM user_db_links;

-- 全スキーマの PRIVATE + PUBLIC リンク(DBA 権限が必要)
SELECT owner, db_link, username, host FROM dba_db_links ORDER BY owner;

-- 接続テスト
SELECT * FROM dual@remote_link;
-- ORA エラーなく '1 row selected' が返れば接続成功
SQL(DB Link の削除)
-- PRIVATE リンクを削除
DROP DATABASE LINK remote_link;

-- PUBLIC リンクを削除(DBA 権限が必要)
DROP PUBLIC DATABASE LINK shared_remote;
SQL(DB Link セッションのクローズ)
-- DB Link 経由で開いたリモートセッションを手動で閉じる
-- (通常はセッション終了時に自動クローズされる)
ALTER SESSION CLOSE DATABASE LINK remote_link;

-- 現在開いている DB Link セッションを確認
SELECT db_link, in_transaction, update_sent
FROM v$dblink;

よくあるエラーと対処法

エラー 原因 対処法
ORA-02019
リモートDBへの接続が確立されていない
DB Link の接続文字列が間違っている、またはリモート DB が停止中 USING 句の接続文字列を確認。tnsping でリモートへの疎通を確認
ORA-12154
TNS: 指定された接続識別子を解決できない
tnsnames.ora にエントリがない、または TNS_ADMIN の設定が不正 tnsnames.ora にエントリを追加するか、Easy Connect 記法を使用
ORA-01017
ユーザー名/パスワードが無効
CONNECT TO のユーザー名またはパスワードが間違い リモート DB にログインできるか手動で確認
ORA-02085
DB Link が別トランザクションに接続中
分散トランザクションが未コミット/未ロールバックのまま COMMIT または ROLLBACK してから再実行
ORA-00942
(DB Link 経由)
リモート側にテーブルが存在しない、または権限不足 リモート側でテーブルの存在と権限を確認
SQL(接続トラブルの診断手順)
-- (1) tnsping でネットワーク疎通を確認
-- $ tnsping REMOTE_DB

-- (2) SQL*Plus でリモート DB に直接ログイン
-- $ sqlplus app_user/secret123@REMOTE_DB

-- (3) DB Link 経由で dual を SELECT(最小限の接続テスト)
SELECT * FROM dual@remote_link;

-- (4) リモート側でテーブルと権限を確認
-- リモートに接続して:
-- SELECT * FROM all_tables WHERE table_name = 'EMPLOYEES';
-- SELECT * FROM user_tab_privs WHERE table_name = 'EMPLOYEES';

セキュリティの注意点

リスク 詳細 対策
パスワード平文格納 CREATE DATABASE LINK の IDENTIFIED BY に指定したパスワードが
データディクショナリに格納される
CURRENT_USER リンクを使うか、リモート側は読み取り専用ユーザーにする
PUBLIC リンクの乱用 全ユーザーがリモート DB にアクセスできてしまう PRIVATE リンクを原則とし、PUBLIC は最小限にする
リモート側の過剰権限 DB Link 用ユーザーが DBA 権限を持っている 専用ユーザーを作成し、必要な SELECT/DML 権限のみ付与
DB Link 用ユーザーの権限は最小限に
リモート DB への接続ユーザーには、必要最小限のオブジェクト権限のみ付与してください。GRANT SELECT ON schema.table TO dblink_user のように参照のみのユーザーにするのが安全です。DBA ロールや UNLIMITED TABLESPACE は絶対に付与しないでください。

よくある質問

QPRIVATE リンクと PUBLIC リンクはどちらを使うべきですか?
A原則としてPRIVATE リンクを推奨します。PRIVATE は作成したユーザーのみ使用可能なため、セキュリティリスクが低いです。複数ユーザーが同じリモート DB にアクセスする必要がある場合でも、PUBLIC リンクではなく各ユーザーに PRIVATE リンクを作成するのが安全です。
Qtnsnames.ora を編集せずに DB Link を作成できますか?
AEasy Connect 記法を使えば tnsnames.ora は不要です。USING '//hostname:1521/service_name' の形式で直接指定できます。テスト目的やシンプルな接続に向いています。
QDB Link 経由の DML は COMMIT が必要ですか?
Aはい。DB Link 経由の INSERT / UPDATE / DELETE はローカルと同様に COMMIT が必要です。ローカルとリモートの DML を同一トランザクションで実行した場合、COMMIT すると両方が確定、ROLLBACK すると両方が取り消されます(分散トランザクション)。
QDB Link 経由のクエリが遅いです
A分散クエリではデータがネットワーク経由で転送されるため、ローカルのクエリより遅くなります。対策は以下の通りです。
(1) WHERE 条件で転送データ量を削減
(2) /*+ DRIVING_SITE(alias) */ ヒントで処理サイトを最適化
(3) 大量データは CTAS でローカルにコピーしてから処理
(4) 定期同期なら Data Pump(expdp/impdp)を使用
QDB Link を DROP せずにパスワードを変更するには?
ADB Link の CONNECT TO パスワードは ALTER 文では変更できません。DROP して再作成するのが唯一の方法です。
DROP DATABASE LINK link_name;
CREATE DATABASE LINK link_name CONNECT TO user IDENTIFIED BY new_password USING ...;
QDB Link 経由で DDL(CREATE TABLE 等)を実行できますか?
ADB Link 経由での DDL は直接実行できません。リモート側で DDL を実行するには DBMS_UTILITY.EXEC_DDL_STATEMENT@link_name を使うか、リモート DB に直接接続して実行してください。

まとめ

Oracle DB Link の作成と管理の要点をまとめます。

やりたいこと 方法
リモート DB に接続する DB Link を作成 CREATE DATABASE LINK link_name CONNECT TO user IDENTIFIED BY pw USING ‘connect_string’
全ユーザーが使える DB Link を作成 CREATE PUBLIC DATABASE LINK …
tnsnames.ora なしで接続 USING ‘//host:port/service_name’(Easy Connect)
パスワードを埋め込まない CONNECT TO CURRENT_USER
リモートテーブルをローカル感覚で使う CREATE SYNONYM local_name FOR table@link
分散クエリを高速化 /*+ DRIVING_SITE(alias) */ ヒント
DB Link の一覧を確認 SELECT * FROM user_db_links
DB Link を削除 DROP [PUBLIC] DATABASE LINK link_name