OPS

Bucardoを用いた古いPostgreSQLからAlloyDB for PostgreSQLへの移行方法

2022.10.03

本記事のポイント

PostgreSQL9以前のデータベースから新しいデータベースへの移行ですが、「現状のデータベースで問題なく利用できている」、「ロジカルレプリケーションに対応していない」などの理由から諦めていませんか?

この記事では、PostgreSQL9.2で構築されたデータベースをGoogle CloudのデータベースサービスAlloyDB for PostgreSQLへ移行する方法を、簡単な実践例を用いてご紹介します。

 

はじめに

皆様の中に最新のクラウド型データベースサービスへの移行を行いたいけど、バージョンが古いため移行を断念している方もいらっしゃるのではないでしょうか? そこで今回は、PostgreSQL9以前のデータベースをBucardoというソフトウェアを用いてGoogle CloudサービスのAlloyDB for PostgreSQLへ移行する方法をご紹介します! 記事前半では利用する機能の概要を、後半では実践例をお伝えするので、是非ご覧ください。

AlloyDB for PostgreSQLの概要

AlloyDB for PostgreSQLとは、Google Cloudが提供するフルマネージド型のデータベースサービスです。 PostgreSQLと互換性を持ちますが、標準的なPostgreSQLとの性能比較テストでは、トランザクション処理で4倍以上、分析クエリで最大100倍の高速化を実現できていることが確認されています。 さらに、無停止でのインスタンスサイズの変更とデータベースメンテナンスに対応しており、メンテナンス含め、 99.99%という非常に高い可用性を実現しております。

Bucardoの概要

Bucardoとは、PostgreSQLのレプリケーションを実現するためのオープンソースソフトウェアです。 トリガ―ベースのレプリケーションシステムであり、複数のマスターとセカンダリを対象に非同期でマルチマスターレプリケーションを実現することが可能です。 ただし、プライマリキーのないテーブルに対してはレプリケーションの設定を行えません。

Bucardoを用いて移行を行う理由

続いて、Bucardoを用いて移行する理由についてお伝えします。 PostgreSQL9以前のPostgreSQLではロジカルレプリケーションに対応しておらず、メジャーバージョンのローリングアップデートを行うことが出来ません。そのため、メジャーバージョンのアップデートを行う際はデータベースへの書き込みを停止させて、データベースの移行を行う必要があります。 Bucardoを用いることで、データベースのデータを新環境に移行している間の更新も保持して、移行先に反映することができるためより少ないダウンタイムでデータベースの移行を実現することが可能です。

PostgreSQL9.2のDBからAlloyDBへの移行の流れ

下記のような手順で移行していきます。
1. AlloyDBとAlloyDB操作用兼、Bucardo用のGCEインスタンスの作成
AlloyDBのクラスタとプライマリインスタンスの作成とAlloyDBを操作するためとBucardoを動作させるためのGCEインスタンスを作成します。
2. AlloyDBの前作業
Bucardoのレプリケーションを行うために先にスキーマが必要なため、ユーザとデータベースを作成して、データベースにスキーマのみ事前に反映しておきます。
3. Bucardoのインストール
Bucardoが設定や変更を保持するためのデータベースの作成を行い、Bucardoを利用できる状態にしておきます。
4. Bucardoのセットアップ
Bucardoにレプリケーションを行うサーバの登録や、テーブルとシーケンスなど同期に必要な情報をBucardoに登録します。
5. Bucardoの同期を開始
データ移行中の変更を保持するためにBucardoの同期を開始します。
6. 旧DBからAlloyDBへデータの移行
pg_dumpとpg_restoreを用いたデータの移行を行います。
7. Bucardoの同期を反映
データ移行中の変更と今後のデータの変更をAlloyDBに反映するためにレプリケーションの同期を開始します。
8. データベースの参照先を変更
データの更新をAlloyDBにのみ書き込みを行えるよう変更します。
9. Bucardoの停止
レプリケーションを停止して旧DBとの同期を切り離します。
10. 移行完了

検証環境の準備

それでは検証環境の作成から実践していきましょう。

1. AlloyDBとAlloyDB操作用兼Bucardo用のGCEインスタンスの作成

AlloyDBのクラスタとプライマリインスタンスを作成します。今回は、検証のため最小構成で作成します。 まずGoogle Cloud Consoleを開き、Compute Engine APIを有効にします。 Compute Engine API 次に、Service Networking APIを有効にします。 Service Networking API 続いてAlloyDB APIを有効にし、「クラスタを作成」をクリックします。 AlloyDB API クラスタを作成 ここではクラスタタイプの選択します。 クラスタタイプを選択 クラスタを構成するこの画面では、後続で作成するGCEが接続できるようなネットワークを利用してください。 接続できるようなネットワークを利用 続いてプライマリインスタンスの構成をします。今回の検証では大きなデータを利用しないため、最小構成のもので作成を行いました。 プライマリインスタンスの構成 ここで、作成したAlloyDBのプライベートアドレスを確認します。(以下、$Alloy_IPとする)以上で、AlloyDBとAlloyDB操作用兼Bucardo用のGCEインスタンスの作成は完了です。 作成したAlloyDBのプライベートアドレスを確認
AlloyDB操作兼Bucardo用GCEインスタンス(以下、bucardo-vm)を作成
今回はネットワークの設定を簡単にして検証を行うためにAlloyDBと同じプロジェクトとVPC上で作成しております。 利用OSはCentOS8 Streamとし、内部IPを$bucardo_IPとします。
移行対象のpostgresql9.2のデータベース用GCEインスタンス(以下、old-db-vm)を作成
今回はネットワークの設定を簡単にして検証を行うためにAlloyDBと同じプロジェクトとVPC上で作成しております。利用したOSはCentOS7、内部IPは$old_db_IP、操作はold-db-vm上で行います。 まず、テスト用DBの作成のために下記をインストールします。
sudo yum -y install postgresql-server postgresql-contrib
  インストールは、以下で行います。
yum list installed | grep postgresql
  自環境での実行結果は、このようになりました。 続いて、クラスタを作成します。
su – postgres
initdb
exit
  bucardo-vmから、操作の許可を行うために下記を修正しておきます。
  • pg_hba.conf : PostgreSQLに接続するクライアントの認証方法を定義するファイルです
  • postgresql.conf : PostgreSQLに関する設定を定義するファイルです
  • listen_addresses : 接続を受け付けるIPを定義する設定です
  続いて、PostgreSQLのサービスを起動します。
sudo systemctl start postgresql.service
  ユーザーとデータベースを作成します。(以下、旧DBとします。)
createuser -s db_user -U postgres
createdb old_db -U db_user
  検証用データを作成します。
pgbench -i old_db -U db_user
  自環境での実行結果は、このようになりました。 検証用データを作成

PostgreSQL 9.2のDBからAlloyDBへの移行方法

2. AlloyDBの前作業

AlloyDBの前作業は、Bucardo-vm上で行います。 まずは、Postgresqlサービスを起動させてPostgresqlをインストールしましょう。
sudo dnf install postgresql-server postgresql-contrib
  以下を使用して、インストールの確認を行います。
dnf list --installed | grep postgresql
Postgresqlをインストール 上記で強制終了されてしまう場合、下記を実行しておきます。
sudo dnf config-manager --disable google-cloud-sdk
  続いて、データベースのユーザーを作成します。まずは、AlloyDBにpsqlを用いてpostgresユーザで接続します。
psql -h $Alloy_IP -U postgres postgres
  次に、ユーザーの作成の作成を行います。ここでは、ユーザ名を「db_user」とします。Created, Replication, loginの権限とパスワードを設定しましょう。
CREATE USER db_user WITH created Replication login password pass_db_user';
  次に、db_userでデータベースの作成を行います。まずは、AlloyDBにpsqlを用いてdb_userユーザで接続しましょう。
psql -h $Alloy_IP -U db_user postgres
  続いて、作成したデータベースへの接続時にパスワードを省略するために、.pgpassを作成します。まずは、pgpassファイルを作り「$Alloy_IP:5432:new_db:db_user:pass_db_user」を書き込みます。
vi .pgpass
chmod 600 .pgpass
  パスワードの入力無しでログインできることを確認します。
psql -h $Alloy_IP -U db_user new_db
  次に、旧DBのスキーマを取得します。オプションの「–schema-only」はスキーマのみダンプを行うもの、「–no-privileges 」はアクセス権限(grant/revokeコマンド)のダンプを抑制するもの、「–schema」は指定したスキーマのみダンプを行うためのものです。
pg_dump -v \
-h $old_db_IP \
-U db_user --schema-only \
 --no-privileges --schema=public old_db \
--file=old_db_schema.sql
  次に、AlloyDBへ旧DBのスキーマを反映します。
psql -h $Alloy_IP -U db_user -d new_db -f old_db_schema.sql
  旧DBのスキーマを反映されたかどうか、以下で確認します。
psql -h $Alloy_IP -U db_user -d new_db -c '\dt'
  自環境での実行結果は、以下の通りになりました。 確認画面

3. Bucardoのインストール

Bucardoのインストールは、bucardo-vm上で行います。まずは、Bucardoの動作に必要なパッケージのインストールしましょう。
sudo dnf install -y epel-release
sudo dnf install -y bucardo perl-open perl-DBI perl-Time-HiRes perl-DBD-Pg perl-DBIx-Safe postgresql-plperl perl-Sys-Syslog perl-Pod-Parser
  続いて、データベースクラスタを作成します。
sudo su – postgres
initdb
exit
  次に、old-db-vmからの操作を許可するための修正しておきます。(例:pg_hba.conf, postgresql.confなど)修正後、PostgreSQLのサービスを起動します。
sudo systemctl start postgresql.service
  次に、Bucardo用のユーザとデータベースを作成します。
createuser -U postgres -s bucardo
createdb -U bucardo -E UTF8 bucardo
  次に、Bucardoのインストールし、Bucardoを確認します。
bucardo --version
  自環境での実行結果は、以下の通りです。 Bucardoを確認 続いて、必要なディレクトリの作成します。
mkdir /var/run/bucardo
mkdir /var/log/bucardo
  次にbucardoデータベースに反映します。
bucardo install -p 5432 -h 127.0.0.1
  自環境での実行結果は、以下の通りです。 Bucardoデータベースに反映

4. Bucardoのセットアップ

この作業は、bucardo-vm上で行います。まずは、旧DBに移行元のDBを登録します。(旧DB)
bucardo add db old_db dbhost=$old_db_IP dbport=5432 \
dbname=old_db dbuser=db_user
  自環境での実行結果はこのようになりました。 移行元のDBの登録 続いて、移行先のDBを登録します。(AlloyDB)
bucardo add db new_db dbhost=$Alloy_IP dbport=5432 \
dbname=new_db dbuser=db_user dbpass=pass_db_user
  自環境での実行結果はこのようになります。 移行先のDBの登録 次に、レプリケートを行うテーブルを登録します。
bucardo add all tables --exclude-table pgbench_history \
 --db=old_db --herd=my_herd --verbose
  自環境での実行結果はこのようになります。「exclude-table」は、レプリケートを行わないテーブルを追加するためのオプションです。 レプリケートを行うテーブルを登録 続いて、レプリケートを行うシーケンスを登録します。今回の実践ではシーケンスが存在しないため実行しませんが、テーブル同様の登録方法で実行します。以下は例です。
bucardo add all sequences --db=old_db --herd=my_herd --verbose
  次に、レプリケートを行うテーブルグループを登録します。今回はマルチマスタレプリケーション形式を利用します。オプションの「source」はマスターとなるDBを指定、「target」はレプリケート先のDBを指定するためのものです。
bucardo add dbgroup my_dbs old_db:source new_db:source
  自環境での実行結果はこのようになります。 DBを指定 続いて、同期の登録を行います、オプションの「autokick」は同期の反映を自動的に行うかの設定(0: オフ, 1: オン)ができます。
bucardo add sync sync_my_dbs relgroup=my_herd dbs=my_dbs autokick=0
  自環境での実行結果はこのようになります。 autokickを0にする ここで、自動同期がオフになっていることを確認します。
bucardo status sync_my_dbs
  自環境での実行結果はこのようになりました。 自動同期がオフになっていることを確認 最後に、設定が正しく行われていることを検証します。
bucardo validate all
  自環境での実行結果は、このようになりました。 設定が正しく行われていることを検証

5. Bucardoの同期を開始

Bucardoの同期は、bucardo-vm上で行います。以下を用いて同期を開始します。
sudo bucardo --loglevel=debug start
  自環境での実行結果はこのようになります。 /var/log/bucardo/log.bucardoに、ログが出力されている事が分かりました。 Bucardoの同期を開始

6. 旧DBからAlloyDBへデータの移行

この作業は、bucardo-vm上で行います。まずは、1つ目の検証のためにbucardoのデルタを確認します。
bucardo delta
  自環境での実行結果はこのようになります。 検証のためbucardoのデルタを確認 続いて、旧DBのデータを取得します。この際、オプションの「Fc: pg_restore」にあった形式でダンプを行います。「blobs:」は ラージオブジェクトもダンプに含んでおり、「N」はダンプしないスキーマを指定できます。
pg_dump -v -h $old_db_IP -U db_user \
--file=old_data.sql -Fc \
--no-privileges --schema=public --blobs \
-N bucardo old_db
  続いて、2つ目の検証のために旧DBにレコードを登録します。
psql -h $old_db_IP old_db -U db_user \
-c "INSERT INTO pgbench_branches VALUES (2, 1, 'test2-1');"
  Bucardo deltaを確認します。
bucardo delta
  自環境の実行結果は、このようになりました。 検証のため旧DBにレコードを登録 次に、旧DBのレコードをAlloyDBへ反映します。オプションの「data-only」はデータのみをリストアします。「disable-triggers」はリストア中のトリガを無効化するものです。
pg_restore -v -h $Alloy_IP -U db_user \
--data-only --disable-triggers -d new_db old_data.sql
  3つ目の検証のため、旧DBにレコードを登録します。
psql -h $old_db_IP old_db -U db_user \
-c "INSERT INTO pgbench_branches VALUES (3, 2, 'test3-2');"
  Bucardo deltaの確認をします。 bucardo deltaの確認 続いて、Bucardo deltaの確認を行い、まずnew_dbの値が0であることを確認します。その後、4つ目の検証のために、旧DBとAlloyDBのテーブル「pgbench_branches」のレコード数を取得します。
psql -h $old_db_IP old_db -U db_user -c "SELECT COUNT(bid) FROM pgbench_branches;"
psql -h $Alloy_IP new_db -U db_user -c "SELECT COUNT(bid) FROM pgbench_branches;"
  レコード数がold_db は3、newdbは1であること確認したら、旧DBからAlloyDBへデータの移行は完了です。 レコード数がnewdbは2でold_db は3であることを確認

7. Bucardoの同期を反映

Bucardoの同期を反映するため、まずは同期を自動実行に変更します。
bucardo update sync sync_my_dbs autokick=1
bucardo reload
  以下で、自動実行に変更されていることを確認します。
bucardo status sync_my_dbs
  その後、autokickがYesになっていることを確認してください。 autokickがYesになっていることを確認 続いて、レプリケーションが行われていることを確認します。
psql -h $old_db_IP old_db -U db_user -c "SELECT COUNT(bid) FROM pgbench_branches;"
psql -h $Alloy_IP new_db -U db_user -c "SELECT COUNT(bid) FROM pgbench_branches;"
  これで、等しい値が取得できていることが確認できます。 等しい値が取得できていることを確認 次に、4つ目の検証のためAlloyDBにレコードを登録します。
psql -h $Alloy_IP new_db -U db_user \
-c "INSERT INTO pgbench_accounts (aid, bid) VALUES (100001, 2);"
  その後、マルチマスタレプリケーション構成になっていることを確認します。
psql -h $old_db_IP old_db -U db_user \
-c "SELECT COUNT(bid) FROM pgbench_accounts;"
psql -h $Alloy_IP new_db -U db_user \
-c "SELECT COUNT(bid) FROM pgbench_accounts;"
  これで、等しい値が取得できていることを確認できました。

8. データベースの参照先を変更

今回の実践では行いませんが、旧DBへの書き込みを停止してWebサービスなどのDB参照をここで切り替えます。

9. Bucardoの停止

Bucardoの停止の際は、データベースの更新内容を反映しないようにします。
bucardo deactivate sync_my_dbs
  自環境で実行すると、以下のようになります。 データベースの更新内容を反映しないようにする 続いて、反映を確認します。
bucardo status sync_my_dbs
  自環境での実行結果は、このようになります。 反映を確認 次に、Bucardoを停止します。
bucardo stop
  実行結果はこのようになります。 Bucardoを停止 次に、各DB上でBucardo作成時に追加されたスキーマとトリガを削除します。
psql -h $old_db_IP old_db -U db_user \
-c "DROP SCHEMA bucardo CASCADE;"
psql -h $Alloy_IP new_db -U db_user \
-c "DROP SCHEMA bucardo CASCADE;"
  Bucardo用データベースとユーザの削除を行います。
dropdb bucardo -U bucardo
dropuser bucardo -U postgres
  Bucardo用フォルダの削除したら、移行は完了です。
sudo rm -rf /var/log/bucardo
sudo rm -rf /var/run/bucardo
 

まとめ

今回は、AlloyDBとBucardoの概要説明とPostgresql9をAlloyDBへ移行する方法をご紹介しました。 実践方法を記述しましたが、今回の方法はストリーミングレプリケーションを実施しており、レコードの取得時間が長いデータベースを対象にした少ないダウンタイムでの実施を目標にした手順での簡易な実践を行いました。 今回は単純なデータベース構成でデータの量が非常に少なく、常に書き込みが行われている訳ではない検証環境での実施だったため、実際の環境に実践する場合はより念密な実行計画作成と検証を行う必要があることにご注意ください。 最後までお読みいただきありがとうございました。