Database Migration Service による移行に向けた PostgreSQL の準備
Google Cloud Japan Team
※この投稿は米国時間 2021 年 4 月 1 日に、Google Cloud blog に投稿されたものの抄訳です。
2020 年 11 月、Google では Database Migration Service(DMS)の一般公開プレビューにより、MySQL ユーザーのユーザーがリレーショナル データベースを容易に移行できるようにしました。現在、このプロダクトは正式に一般提供され、同様の使いやすい移行機能が PostgreSQL に導入されています。
私が DMS を使い込んでみて見出したその真価は、DMS が容易に機能することでした。移行元のインスタンスとデータベースを用意し、移行元と移行先を接続すると、移行処理がすべて実行されます。すべての移行処理が完了すると、DMS の UI でボタンをクリックするだけの簡単な操作で、アプリケーションの主要データベースとして Cloud SQL インスタンスを使用するためのカットオーバーが始まります。
データベースの準備や接続性の難しさを軽視しないほうが良いでしょう。DMS の豊富な接続性オプションについては、ブログ投稿で詳しく説明しています。ネットワーク トポロジはきわめて複雑であることが考えられます。また、2 台のマシンをセキュリティで保護してインターネットで接続しながら、数千人から数百万人のユーザーにアプリケーションを提供することは、決して容易ではありません。
DMS を使用して移行できるように移行元の PostgreSQL のインスタンスとデータベースを準備する手順について、ここで少しご説明します。また、皆様の便宜も考慮して、移行に関するヒントもいくつかご紹介します。
まず、ドキュメントとプロダクトに組み込まれている UI ガイドの両方が、DMS にきわめて効果的であることをお伝えします。PostgreSQL のレプリケーション インフラストラクチャの設定に習熟している方であれば、移行に携わるうえで適任であり、必要に応じてドキュメントを確認すれば移行を進めることができると思われます。そうは言っても、このドキュメントについて若干の補足説明はしておきたいと思います。それにより、このドキュメントは、PostgreSQL のインスタンスとデータベースの準備に必要なすべての知見が詰まった資料になります。
最初の手順は、移行元のインスタンスのバージョンがサポート対象であることの確認です。サポート対象バージョンの最新リストはドキュメントのページ I にあります。そのページへのリンクは前述のとおりです。
次にスキーマ上の注意点です。DMS では、主キーが設定されていないテーブルの移行をサポートしていません。主キーがないテーブルを収めたデータベースの移行を正常に開始することはできます。しかし、主キーが欠落したテーブルそのものは作成されますが、そのデータは移行元から引き継がれません。したがって、主キーがないテーブルのデータを引き継ぐために、次のオプションが用意されています。
移行に着手する前に、テーブルに主キーを追加します。
最初の移行の後、ユーザー自身の手でデータを引き継ぎます。当然のことながら、自身でデータを引き継ぐ場合は、接続を維持していても、DMS ではそのテーブルのデータは複製されず、移行は先に進んでいくことに留意する必要があります。
移行元のインスタンスからテーブルをエクスポートして、新しいインスタンスにインポートできます。
最後の方法として、主キーを持たない手元のテーブルと同じスキーマでテーブルを作成し、主キーを設定します(キーを自動生成するシーケンス ジェネレータを使用します)。これで移行元のデータをそのテーブルにコピーできるようになります。続いて移行を実施します。移行の過程で使用する DMS では、主キーがないテーブルが作成されるので、移行元のデータがコピーされて引き継がれることはありません。これで、移行元の主キーテーブルからデータをコピーできます。最後に、コピーしたデータを検証して問題がなければ、主キーテーブルを削除できます。この手順は複雑に思われますが、主キーがないテーブルに新しい行をすべて挿入済みであれば、移行の時点で移行元に残っているデータと同じデータが移行先に確実に得られ、主キーもコピーできます。移行中に移行元のテーブルでデータが変更される懸念がある場合は、移行先のインスタンスをプロモートする直前にデータをコピーして引き継ぎます。これにより、そのようにデータが変更される可能性がある期間を最小限にすることができます。
DMS では、移行の作業で pglogical が使用されています。したがって、移行するデータベースのそれぞれに pglogical 拡張機能をインストールしておく必要があります。インスタンスとデータベースに pglogical をインストールする方法については、こちらに説明があります。Linux 上で実行している場合は、リポジトリのインストール ページが役に立ちます。興味をお持ちの方がいらっしゃると思いますので、Homebrew を使用してインストールした PostgreSQL データベースを MacOS から Cloud SQL に移行することにどのような問題があるかを確認してみました。驚いたことに、決して悪くないことがわかりました。次のように、ソースから pglogical をインストールします。
1)GitHub リポジトリのクローンを作成します。
2)make を実行します。
2a)postgres.h が見つからないのでコンパイル エラーが発生します。
3)Homebrew によって Postgre がインストールされている場所を確認し、include フォルダを探してすべての include フォルダを C_INCLUDE_PATH に追加します。
4)再度 make を実行してビルドします。
5)pglogical のドキュメントには sudo が必要になることが記載されているので、sudo make install を実行します(注: 事前最適化は実施しないでください)。
5a)明確なメッセージが示されずに失敗します。
6)make install を実行します。
7)これで正常に完了できました。これでテストが問題なく終了したわけではありません。インスタンスとデータベースを、pglogical とレプリケーションを使用するように構成する必要があるからです。
PostgreSQL でレプリケーションを手がけたことがあれば、次の手順はきわめて簡単です。レプリケーションが正常に機能するように、インスタンスに構成変数をいくつか設定する必要があります。これらの変数の値を変更するには、主に 2 つの方法があります。1 つはインスタンスを実行している状態で ALTER SYSTEM SET <variable> TO <value>; の呼び出しを使用して値を調整する方法です。もう 1 つは構成ファイル posgresql.conf で値を変更する方法です。どちらの方法でも、変更を反映するにはインスタンスの再起動が必要です。
構成ファイルで変数値を変更する場合は、その変数の場所がわかっている必要があります。一般的には、データベースのデータ ディレクトリにこれらの変数が置かれています。自身のデータベースにログインするための認証情報のみがあり、そのデータ ディレクトリの場所が不明な場合は、データベースに接続して SHOW data_directory を実行します。これで、データ ディレクトリの場所がわかります。
設定を必要とする変数は次のとおりです。
wal_level = logical # logical に設定します。
max_replication_slots = n # 数値 n は状況に応じて異なります。詳細については、こちらをご覧ください。
max_wal_senders = n # アクティブな状態で接続されているレプリカの数を max_replication_slots の値に加算した値とします。
max_worker_processes = n # 複製するデータベースの数に設定します。
shared_preload_libraries = pglogical
shared_preload_libraries 変数はカンマ区切りリストです。この変数を設定するときに注意を要する点は、インクルードするためにプリロードされているライブラリが他にないかの確認が事前に必要なことです。この確認を怠ると、手順の進行に伴って必須のライブラリがアンロードされ、データベースの問題が発生する原因になります。
インスタンスを再起動すると、接続して SHOW <variable> を実行することで変数値の変更を確認できます。たとえば、SHOW wal_level では logical が返される必要があります。
簡単な例のご紹介:
以下の数値は DMS の読み込みにのみ適用されます。これらの値を他の理由ですでに設定している場合は、その点を考慮する必要があります。たとえば、同時に発行できるクエリの数を多くするために max_worker_processes を 8 に設定している場合は、レプリケーションの処理でパフォーマンスが低下しないように、この値をさらに大きくする必要があります。
ケース 1: 移行を実施し、直ちに Cloud SQL のインスタンスをプロモートします。移行元に設定しているレプリカは他になく、移行の対象とするデータベースは 1 つのみです。これらの値を次のように設定します。
# 技術的には、Cloud SQL サブスクライバーについて 1 が必要になるだけです。
# デフォルト値は 10 に設定されているので、このデフォルト値のままとします。また、これより小さい値に設定しても、
# 問題はありません。
max_replication_slots = 3
# 移行元インスタンスに接続しているレプリカは 1 つのみなので
# max_replication_slots + 1 に等しい値に設定します。
max_wal_senders = 4
# 移行の対象とするデータベースは 1 つのみなので、技術的には
# 値 1 のみが必要です。しかし、問題が発生した場合を考慮して
# 複数のプロセッサを使用するので、バッファとして必ず 1 を
# 見込むことが得策です。
max_worker_processes = 2
ケース 2: オンプレミスのローカル インスタンスに 5 つのレプリケーション スロットを設定して、配備済みのレプリケーションを扱うようにした環境を考えます。Cloud へ移行するデータベースがこの環境に 4 つある場合、各変数を次のように設定します。
# 既存のサブスクライバー向けに 5 を考慮し、pglogical で移行元データベースごとに
# 1 つのスロットを必要とするので 4 を考慮します。
max_replication_slots = 9
# 既存のレプリカが 5 つあるほか、移行を実施する DMS 用のレプリカを
# 1 つ追加するので、max_replication_slots + 6 に等しい値とします。
max_wal_senders = 15
# 移行するデータベース向けに 4 を考慮し、予備としてバッファ向けに 1 を考慮します。
max_worker_processes = 5
これらの変数をすべて設定した後、構成ファイルで変数値を変更した場合は、PostgreSQL インスタンスを再起動する必要があります。
pglogical が機能していることを確認するには、インスタンスにログインして、複製を予定しているデータベースのいずれかで CREATE EXTENSION pglogical を実行します。pglogical が機能していれば、複製する各データベースに接続して、それぞれで同じコマンドを実行します。また、各データベースに接続しているときに、移行を作成したソースの定義の手順で指定したユーザーに、一定の権限を付与する必要があります。以下の権限付与を、複製するデータベースのほか、postgre データベースでも実施する必要があります。
# pglogical も含め、移行する各データベース上のすべてのスキーマ(情報スキーマと名前が "pg_" で始まるスキーマを除きます)で実施します。
GRANT USAGE on SCHEMA <SCHEMA> to <USER>
# 移行元データベースからレプリケーション情報を取得するすべてのデータベースで実施します。
GRANT SELECT on ALL TABLES in SCHEMA pglogical to <USER>
# pglogical も含め、移行する各データベース上のすべてのスキーマ(情報スキーマと名前が "pg_" で始まるスキーマを除きます)で実施します。
GRANT SELECT on ALL TABLES in SCHEMA <SCHEMA> to <USER>
# pglogical も含め、移行する各データベース上のすべてのスキーマ(情報スキーマと名前が "pg_" で始まるスキーマを除きます)で実施します。
GRANT SELECT on ALL SEQUENCES in SCHEMA <SCHEMA> to <USER>
# このブログ投稿では、この権限付与は取り上げませんが、RDS から複製する場合、
# この権限付与は GRANT rds_replication TO USER となります。
ALTER USER USER WITH REPLICATION
移行元データベースのバージョンが 9.6 よりも前の場合は、追加の手順があります。9.6 よりも前のバージョンでは、レプリケーションの遅延をモニタリングする機能が、デフォルトでは PostgreSQL にないからです。DMS では、レプリケーションの遅延が過剰になっているかどうかを、この機能で確認できるようにしているため、この手順が必要になります。ここでは、これについてこれ以上は取り上げません。現時点で、9.6 よりも前のバージョンはすべてサポートを終了しているからです。そのようなバージョンを扱う場合は、必要な対応に関する情報をこちらでご覧ください。
お疲れさまでした。これで、PostgreSQL のインスタンスとデータベースの構成がすべて完了し、DMS で処理できるようになりました。DMS のもう一つの優れている点は、すべての構成を完了して移行へ進む段階まで来たときに、接続性と構成をテストする機能が UI に用意されていることです。このテストによって、移行前の最後の操作である「実際に移行を実施」するボタンをクリックする前に、すべての構成が正しいかどうかを確認できます。
この投稿の冒頭にあるリンク先のブログ投稿で、移行元データベースと Cloud SQL インスタンスとの接続性の核心に迫る詳しい情報を数多く取り上げていることはお知らせしたとおりです。そのブログでは MySQL を扱っているので、ここでは、これまで PostgreSQL でつまずいた経験を追記して、この投稿を終わりたいと思います。
それは、ローカルホストではない場所からの接続をデータベースでリッスンし、許可できるようにするということです。そのようにしていない場合は、必ずこのための措置を実施してください。そのために 2 つの手順を踏みます。まず、postgresql.conf ファイルの listen_address 変数を変更する必要があります。この変数のデフォルト値は localhost です。アプリケーションからデータベースへの接続の管理方法によっては、このデフォルト値でも機能する可能性がありますが、移行では機能しません。次に、移行のために Cloud からローカル データベースにアクセスする権限がユーザーに付与されるように pg_hba.conf ファイルを修正する必要もあります。これらの手順のいずれも実施していないと、移行できないことを通知するエラー メッセージが PostgreSQL のインスタンスから発行されます(DMS の優れている点です)。これを知ることになった経緯については、私まで別途お問い合わせください。
以上で、このブログ投稿の結びといたします。DMS を使用すれば、PostgreSQL データベースを Cloud SQL に移行するうえで必要な手順をすべて実施できます。ご質問、ご提案、ご意見などがありましたら、Twitter で私にご連絡ください。DM は開いています。最後までお読みいただきありがとうございました。
-デベロッパー アドボケイト Gabe Weiss