すべてのプロダクト
Search
ドキュメントセンター

PolarDB:mysql_fdw

最終更新日:Apr 25, 2025

mysql_fdw は、PolarDB for PostgreSQL クラスタが PolarDB for MySQL インスタンス、ApsaraDB RDS for MySQL インスタンス、およびセルフマネージド MySQL インスタンスからデータを読み書きできるようにするオープンソースのサードパーティ拡張機能です。

前提条件

この拡張機能は、次のエンジンを実行する PolarDB for PostgreSQL クラスタでサポートされています。

  • PostgreSQL 16(リビジョンバージョン 2.0.16.6.2.0 以降)

  • PostgreSQL 15(リビジョンバージョン 2.0.15.12.4.0 以降)

  • PostgreSQL 14(リビジョンバージョン 2.0.14.11.19.0 以降)

  • PostgreSQL 11(リビジョンバージョン 2.0.11.9.34.0 以降)

説明

コンソールでリビジョンバージョンを表示するか、SHOW polardb_version; 文を実行してリビジョンバージョンをクエリできます。リビジョンバージョンをアップグレードする必要がある場合は、バージョン管理を参照してください。

使用方法に関する注意事項

  • PolarDB for PostgreSQL クラスタが属する VPC の CIDR ブロックを追加して、クラスタが MySQL インスタンスと通信できるようにする必要があります。CIDR ブロックの例は、172.xx.xx.xx/16 です。

  • PolarDB for PostgreSQL では、OPTIONS 文で host キーワードと port キーワードを指定することはできません。代わりに channel_name を使用してください。デフォルトでは、各クラスタは localhost という名前の channel で構成されています。これは、ローカルサーバーに接続するための channel です。他のクラスタに接続する場合は、最初に channel を作成します。channel を構成する必要がある場合は、お問い合わせください

使用方法

  1. mysql_fdw 拡張機能を作成します。

    CREATE EXTENSION IF NOT EXISTS mysql_fdw;
    説明

    この文を実行できるのは、特権アカウントのみです。

  2. MySQL サーバーを定義します。

    CREATE SERVER <サーバー名>
        FOREIGN DATA WRAPPER mysql_fdw
        OPTIONS (channel_name 'チャネル名'); 
    説明

    PolarDB for PostgreSQL では、OPTIONS 文で channel_name を使用することによってのみ、MySQL インスタンスの接続情報を指定できます。

    次のサンプルコードでは、mysqlchannel という名前の polar_channel が使用されています。

    CREATE SERVER mysql_server
         FOREIGN DATA WRAPPER mysql_fdw
         OPTIONS (channel_name 'mysqlchannel');
  3. MySQL サーバーを PolarDB for PostgreSQL クラスタのアカウントにマップするユーザーマッピングを作成します。このアカウントを使用して、MySQL サーバー上にある MySQL データベースのデータを読み書きできます。

    CREATE USER MAPPING FOR <PolarDB for PostgreSQL ユーザー名>
    SERVER <MySQL サーバーの名前>
    OPTIONS (username '<MySQL ユーザー名>', password '<MySQL ユーザーのパスワード>'); 

    例:

    CREATE USER MAPPING FOR pgtest
    SERVER mysql_server
    OPTIONS (username 'mysqltest', password 'Test1234!');
  4. 手順 3 で指定されている PolarDB for PostgreSQL ユーザーを使用して、MySQL インスタンスの外部テーブルを作成します。

    説明

    外部 MySQL テーブルのフィールド名は、MySQL データベースのテーブルのフィールド名と同じである必要があります。クエリするフィールドのみを作成することもできます。たとえば、MySQL データベースのテーブルに ID、NAME、AGE フィールドが含まれている場合、外部 MySQL テーブルに ID フィールドと NAME フィールドを作成できます。

    CREATE FOREIGN TABLE <テーブル名> (<フィールド名> <データ型>,<フィールド名> <データ型>...) server <サーバー名> options (dbname '<MySQL データベース名>', table_name '<MySQL テーブル名>');

    例:

    CREATE FOREIGN TABLE ft_test (id1 int, name1 text) server mysql_server options (dbname 'test123', table_name 'test');
  5. MySQL データベースに対する読み取り操作と書き込み操作を実行できるかどうかを確認します。

    • 外部 MySQL テーブルを使用して、MySQL データベースに対する読み取り操作と書き込み操作を実行できるかどうかを確認できます。

      説明

      MySQL データベースのテーブルにプライマリキーが割り当てられている場合にのみ、テーブルにデータを書き込むことができます。テーブルにプライマリキーが割り当てられていない場合は、次のエラーが返されます。

      ERROR:  first column of remote table must be unique for INSERT/UPDATE/DELETE operation.
      SELECT * FROM ft_test ;
      INSERT INTO ft_test VALUES (2,'abc');
      INSERT 0 1
      INSERT INTO ft_test SELECT generate_series(3,100),'abc';
      INSERT 0 98
      SELECT count(*) FROM ft_test ;
       count
      -------
          99
      (1 row)
    • 実行計画を表示して、PolarDB for PostgreSQL クラスタが MySQL データベースからデータをクエリするために送信したリクエストの実行方法を確認します。

      explain verbose SELECT count(*) FROM ft_test ;
                                        QUERY PLAN
      -------------------------------------------------------------------------------
       Aggregate  (cost=1027.50..1027.51 rows=1 width=8)
         Output: count(*)
         ->  Foreign Scan on public.ft_test  (cost=25.00..1025.00 rows=1000 width=0)
               Output: id, info
               Remote server startup cost: 25
               Remote query: SELECT NULL FROM `test123`.`test`
      (6 rows)
      
      explain verbose SELECT id FROM ft_test WHERE id=2;
                                     QUERY PLAN
      -------------------------------------------------------------------------
       Foreign Scan on public.ft_test  (cost=25.00..1025.00 rows=1000 width=4)
         Output: id
         Remote server startup cost: 25
         Remote query: SELECT `id` FROM `test123`.`test` WHERE ((`id` = 2))
      (4 rows)