はじめに
Google CloudとOCIをクロスクラウド接続し、その接続経由で Cloud SQL for PostgreSQL から Oracle Database(BaseDB)へ oracle_fdw を利用して直接接続してみた話です。
Google CloudとOCIはクロスクラウド接続で直接接続することが可能です。
一方、Google CloudではCloud SQLやAlloyDBは内部VPCに配置されるため、直接他のVPCと接続することはできません。ただ、次の記事によると、BGPにカスタムルートを設定することで他のVPCとも接続することができる、というような記載がありましたので、クロスクラウド接続でも同様に行うことができるのではと思い試してみました。
テスト構成
Google Cloud上のCloud SQLからクロスクラウド接続経由でOCIのOracle Database(BaseDB)へリンク(oracle_fdw)で接続してみました。
ネットワーク接続 追加設定ポイント
- Cloud Routerへカスタムルートの追加
利用している Cloud Router の「カスタムIP範囲」にCloud SQLのInternal VPCを追加します。今回はCloud SQLのInternal VPCのCIDRである 10.102.96.0/24 ですね。
- VPCピアリングへカスタムルート交換の追加
次図のように、ピアリング設定でカスタムルートの交換に「カスタムルートのインポートとエクスポート」を追加します。
設定すると、OCI側のDynamic Routing Gateway (DRG)のルートに 10.102.96.0/24 (Cloud SQLのネット和ワーク) が追加されます。
Cloud SQLからOracle Databaseへの接続
※それぞれのVPC/VCNのネットワーク設定でファイやウォールなどの設定は事前に行っておく必要があります
エクステンションインストール
まずはCloud SQLに接続し、oracle_fdw extensionをインストールします。
$ psql -h 10.102.96.5 -p 5432 -U postgres -d postgres
Password for user postgres:
psql (10.23, server 16.3)
WARNING: psql major version 10, server major version 16.
Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
postgres=> CREATE EXTENSION oracle_fdw;
CREATE EXTENSION
postgres=> \dew+
List of foreign-data wrappers
Name | Owner | Handler | Validator | Access privileges | FDW options | Description
------------+----------+--------------------+----------------------+-------------------+-------------+-----------------------------
oracle_fdw | postgres | oracle_fdw_handler | oracle_fdw_validator | | | Oracle foreign data wrapper
postgres=> SELECT name, default_version FROM pg_available_extensions WHERE name LIKE 'oracle%';
name | default_version
------------+-----------------
oracle_fdw | 1.2
(1 row)
postgres=> SELECT oracle_diag();
oracle_diag
--------------------------------------------------------------------------------
oracle_fdw 2.6.0, PostgreSQL 16.3, Oracle client 21.10.0.0.0, ORACLE_HOME=/lib
(1 row)
外部サーバー設定
BaseDBを ora_server という名前で、PostgreSQL上で設定します。
postgres=> CREATE SERVER ora_server FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '192.168.1.25:1521/PDBTEST.testsub.testvpc.oraclevcn.com');
CREATE SERVER
postgres=> \des+
List of foreign servers
Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description
------------+----------+----------------------+---------------------+------+---------+----------------------------------------------------------------------+-------------
ora_server | postgres | oracle_fdw | postgres=U/postgres | | | (dbserver '192.168.1.25:1521/PDBTEST.testsub.testvpc.oraclevcn.com') |
(1 row)
ユーザマッピング設定
Oracle Database上の HR ユーザを postgres ユーザとマッピングします。
postgres=> CREATE USER MAPPING FOR postgres SERVER ora_server OPTIONS (user 'HR', password '********');
CREATE USER
postgres=> \deu+
List of user mappings
Server | User name | FDW options
------------+-----------+------------------------------------------
ora_server | postgres | ("user" 'HR', password '********')
(1 row)
外部テーブル設定
PostgreSQL上で f_ora_tbl というテーブルを外部テーブル(Oracle Database上)として作成して、データを挿入してみます。
postgres=> CREATE FOREIGN TABLE f_ora_tbl(
id integer OPTIONS (key 'true'),
name varchar(128),
update_time timestamp)
SERVER ora_server OPTIONS (schema 'HR',table 'ORA_TBL');
CREATE FOREIGN TABLE
postgres=> \d
List of relations
Schema | Name | Type | Owner
--------+-----------+---------------+----------
public | f_ora_tbl | foreign table | postgres
(1 row)
postgres=> insert into f_ora_tbl values(1, 'asahide', current_timestamp);
INSERT 0 1
postgres=> commit;
WARNING: there is no transaction in progress
COMMIT
postgres=> select * from f_ora_tbl;
id | name | update_time
----+---------+----------------------------
1 | asahide | 2024-09-27 13:48:27.917989
(1 row)
SQL> desc ora_tbl
Name Null? Type
---------------- -------- ---------------------
ID NOT NULL NUMBER
NAME VARCHAR2(128)
UPDATE_TIME TIMESTAMP(6)
SQL> select * from ora_tbl;
ID NAME UPDATE_TIME
---------- ---------- --------------------------------------------------
1 asahide 27-SEP-24 01.48.27.917989 PM
まとめ
BGP周りの設定については具体的な方法の記載がなかったためかなり試行錯誤しましたが、結果的には繋がってよかったです。。
今回はCloud SQLで実行しましたが、もちろんAlloyDBでも行うことが可能です。
クラウド同士が接続されることで、DMSなどを利用したデータ移行だけでなく、今回紹介したような直接的なデータベース接続なども今後は行われていくのでしょうか。
おまけ
PostgreSQL上からの実行計画の確認結果です。
postgres=> EXPLAIN (analyze, verbose) SELECT * FROM f_ora_tbl;
QUERY PLAN
------------------------------------------------------------------------
Foreign Scan on public.f_ora_tbl (cost=10000.00..20000.00 rows=1000 width=286) (actual time=2.293..2.302 rows=
1 loops=1)
Output: id, name, update_time
Oracle query: SELECT /*d9e8e872b767a314*/ r1."ID", r1."NAME", r1."UPDATE_TIME" FROM "HR"."ORA_TBL" r1
Oracle plan: SELECT STATEMENT
Oracle plan: TABLE ACCESS FULL ORA_TBL
Query Identifier: -4152246345055789969
Planning Time: 6.254 ms
Execution Time: 2.344 ms
(8 rows)
参考
oracle_fdw周りは以下を参考にさせて頂きました。