Oracle のDBリンク(データベースリンク)は、あるデータベースから別のデータベースに対して SQL を実行するための接続オブジェクトです。本番とテスト環境間のデータ比較、複数拠点のデータ統合、リモートテーブルのコピーなど、複数 DB をまたぐ操作で活躍します。
本記事では、CREATE DATABASE LINK の構文から、PRIVATE / PUBLIC の違い、Easy Connect 記法と tnsnames.ora の使い分け、DB Link 経由の SELECT / INSERT / CTAS、DRIVING_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 の基本構文
-- 構文 CREATE [PUBLIC] DATABASE LINK link_name CONNECT TO remote_user IDENTIFIED BY remote_password USING 'connect_string'; -- connect_string: tnsnames.ora のエントリ名、または Easy Connect 記法
-- tnsnames.ora に REMOTE_DB というエントリがある場合 CREATE DATABASE LINK remote_link CONNECT TO app_user IDENTIFIED BY secret123 USING 'REMOTE_DB'; -- 作成後の使い方 SELECT * FROM employees@remote_link;
-- 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 の編集が不要でシンプル。テスト環境向き
・tnsnames.ora: ホスト変更時に tnsnames.ora だけ修正すればよい。本番環境推奨
ネットワーク設定の詳細は「リスナー設定完全解説」を参照してください。
PRIVATE リンクと PUBLIC リンクの違い
| 種類 | 作成構文 | 使用できるユーザー | 必要な権限 |
|---|---|---|---|
| PRIVATE(デフォルト) | CREATE DATABASE LINK … | 作成したユーザーのみ | CREATE DATABASE LINK |
| PUBLIC | CREATE PUBLIC DATABASE LINK … | 全ユーザー | CREATE PUBLIC DATABASE LINK |
-- 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 リンクは全ユーザーがリモート DB にアクセスできるため、権限管理が甘いと意図しないデータ漏洩につながります。本番環境ではPRIVATE リンクを推奨し、PUBLIC リンクは読み取り専用(SELECT 権限のみ)のユーザーで接続してください。
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 経由のデータ操作
-- 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 が必要
-- リモートのテーブル構造+データをローカルにコピー 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 を毎回書くのは煩雑です。シノニムを作成すれば、ローカルテーブルと同じ感覚でアクセスできます。
-- リモートテーブルへのシノニムを作成 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 ヒントで処理を実行するサイトを指定できます。
-- デフォルト: ローカル側で結合(リモートから全データを転送してくる)
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 の確認・削除・クローズ
-- 自分が作成した 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' が返れば接続成功
-- PRIVATE リンクを削除 DROP DATABASE LINK remote_link; -- PUBLIC リンクを削除(DBA 権限が必要) DROP PUBLIC DATABASE LINK shared_remote;
-- 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 経由) |
リモート側にテーブルが存在しない、または権限不足 | リモート側でテーブルの存在と権限を確認 |
-- (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 への接続ユーザーには、必要最小限のオブジェクト権限のみ付与してください。
GRANT SELECT ON schema.table TO dblink_user のように参照のみのユーザーにするのが安全です。DBA ロールや UNLIMITED TABLESPACE は絶対に付与しないでください。よくある質問
USING '//hostname:1521/service_name' の形式で直接指定できます。テスト目的やシンプルな接続に向いています。(1) WHERE 条件で転送データ量を削減
(2)
/*+ DRIVING_SITE(alias) */ ヒントで処理サイトを最適化(3) 大量データは CTAS でローカルにコピーしてから処理
(4) 定期同期なら Data Pump(expdp/impdp)を使用
DROP DATABASE LINK link_name;CREATE DATABASE LINK link_name CONNECT TO user IDENTIFIED BY new_password USING ...;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 |

