おことわり
まず、筆者の所属するPingCAP株式会社はこの使い方について言及も推奨もしていないということを明確にしておきます 以降の記載は筆者が個人として試したものです。ご利用は自己責任で!
PostgreSQLからTiDB使えないんですか?
気持ちは分かります。というかTiDBのストレージレイヤであるTiKVはSQLからは中立ですし、TiDBにしてもSQLをパースしてASTにしてからは比較的SQLの文法的な部分の影響は薄いはず(未確認)です。なのでpgsqlプロトコルとPostgreSQL方言のSQLパーサーがあれば、PostgreSQL互換にもできるはず・・・というところで実際そのような派生プロジェクトも見つけたりしました。
しかし恐らくこのような質問をする方の意図というのは公式リリースのTiDBをPostgreSQLから使いたいということであり、そのような実現方法がないか考えるべきでしょう。いや単に興味あっただけですすいません。
FDW - Foreign Data WrapperでTiDBを利用する
dbtsで劔やSCALARDBの話を聞いたときに、しきりにPostgreSQLのFDWを使っているということを言っていました。調べてみるとpostgreSQLから外部テーブルとして他のDBを利用出来る機能ということじゃないですか!
更にEDBが作成したmysql用のFDWmysql_fdwというものも発見し、これはdbtsコラボ(勝手に)だ! ということで実際にpostgreSQLからmysql_fdw経由でTiDBを利用できるか試して見ました。
AWSにt3.xlargeのインスタンスを立ち上げ、postgreSQLとTiDB(Playground)を同一のマシンで動かして連携してみます。以降の作業は全てAWSインスタンス上の作業です。EC2にPublic IPを付与して、一台構成で行っています。
1. [PostgreSQL] EPAS + mysql_fdwのインストール
EDB Postgres Advanced Server(EPAS) とmysql_fdwのインストールにはEDB repositoryへのアクセスが必要です。mysql_fdwはgithub上でソースも公開されているので、そちらをコンパイルしてPostgreSQLと組み合わせても動くのですが、今回はバイナリインストールすればできる上記の組み合わせで試します。アカウントがない場合はページ下部のCreate EDB Account
から作成できます。
ログイン後、メニューから Repo Access
を選びます。
その後に出てくる画面でAccess Repo 2.0
ボタンを押して、リポジトリに進みます。
その後に出てくるOSと製品選択画面で、Ubuntu 22.04
、EDB Postgres Advanced Server 16
、MySQL 8 FDW for EPAS 16
を選択します。リストが膨大なので、Advanced ServerやMySQLで検索すると見つけやすいです。
選択すると画面右側にリポジトリの自動セットアップスクリプトと、インストール手順が表示されます。自動セットアップは個人トークンが含まれるようですのでここでは割愛します。リポジトリが設定できればインストールは簡単です。
> sudo apt-get -y install edb-as16-server edb-as16-mysql8-fdw
なおこのリポジトリからはPostgreSQLとPostgreSQL用のmysql_fdwもインストールできるので、そちらでも同様に動作するものと思いますが未検証です。
インストール後の設定等は公式ガイド に記載のものを実施しています。
2. [TiDB] TiDBのインストール
TiDBはEDBと同じサーバで動かせるように、一台で動作するTiDB Playgroundを利用します。TiDB PlaygroundについてはAdvent Calendarの三日目を参照ください。
インストールは簡単で
> curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
> tiup playground
です。これでTiDBがlocalhostで起動します。
3. [TiDB] サンプルテーブルの作成
アクセス確認用に適当なテーブルを作成します。Ubuntuサーバの別のコンソールを開き、TiDBに接続します。
> tiup client connect
適当なテーブルを作成します。ChatGPTに作ってもらいました。
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
position VARCHAR(100),
salary DECIMAL(10, 2),
hire_date DATE
);
-- サンプルデータの挿入
INSERT INTO employees (name, position, salary, hire_date)
VALUES
('田中 一郎', 'マネージャー', 600000, '2018-06-23'),
('鈴木 花子', '開発者', 450000, '2019-07-15'),
('佐藤 太郎', 'アナリスト', 500000, '2020-01-10');
4. [PostgreSQL] Foreign Tableの作成
PostgreSQL側でTiDBを参照するForeign Tableを作っていきます。
初回はまずmysql_fdw
拡張機能を有効にする必要があります。
CREATE EXTENSION mysql_fdw;
次に、TiDBサーバの情報と、利用するユーザーのマッピングを定義します。今回はお試しなので特権ユーザー同士をマッピングしていますが、実際に運用するときはこの辺ちゃんと考えないといけないでしょう。
CREATE SERVER mysql_server
FOREIGN DATA WRAPPER mysql_fdw
OPTIONS (host '127.0.0.1', port '4000');
CREATE USER MAPPING FOR enterprisedb
SERVER mysql_server OPTIONS (username 'root', password '');
最後に、PostgreSQL側にTiDBと同じテーブルを定義する必要があります。これは自分で定義を合わせて作ってもよいですが(ChatGPTにMySQLのDDL食わせてPostgresに変換を依頼すると簡単にできます。便利ですね!)、TiDB側の定義をIMPORTする手段があるのでそれを利用します。
TiDBのtestデータベースにあるテーブル定義をpublicに読み込んでいます。
IMPORT FOREIGN SCHEMA test
FROM SERVER mysql_server INTO public;
5. [PostgreSQL] クエリ
ここまで問題なくできていれば、後はクエリを投げるだけです。前段の準備も含めた実行結果です。
まとめ
今回使った道具はどれもTiDBと動かすことは想定していないので、予期しない挙動が発生することは十分に考えられます。
今回使った範囲でも、ローカルのTiDBクラスタは大丈夫なのですが、TLSが必須のTiDB Serverlessでは動作しませんでした。クエリは通っているので恐らくレスポンス返却時の処理のどこかで詰まっている気がしますがちょっとわかりません。
ただこんなことも出来るんだ、というのでちょっと面白かったです。興味のある方はPrivate LinkなどTLSが不要な環境で試して見るとTiDB Cloudとでも動かせるかもしれません。動いたら是非ブログで!