Zeabur の PostgreSQL を Zenavo に移行する:バックアップの復元とデータの確認

Zeabur からエクスポートした PostgreSQL バックアップをそのまま Zenavo にアップロードして復元します。メジャーバージョン、ロール権限、pg_dumpall クラスターダンプの扱い、復元後のデータ確認と切り替え手順を説明します。

この記事は English、简体中文、繁體中文、Español、Bahasa Indonesia でもお読みいただけます。

Zeabur から引っ越すとき、アプリのサービス構成はテンプレートのインポートでそのまま作れますが、データベースの中身はバックアップを使って移します。

Zenavo は Zeabur からダウンロードした PostgreSQL のバックアップファイルをそのまま受け付けるため、手元で展開したり SQL を書き換えたりする必要はありません。この記事では、Zeabur の PostgreSQL バックアップを Zenavo に復元し、中身を確認してアプリを切り替えるまでの手順を説明します。プロジェクト全体の移行手順は Zeabur からの移行ガイドとあわせてご覧ください。

1. Zeabur からバックアップをダウンロードする

Zeabur の PostgreSQL サービスでバックアップをダウンロードし、あわせて次の2つを控えておきます。

  • PostgreSQL のメジャーバージョン(15、16、17 など)
  • アプリが実際に使っているデータベース名

Zeabur からダウンロードされるファイルは通常 .zip アーカイブ(ファイル名が .sql.gz になっていても中身の外側は ZIP のことがあります)で、中に pg_dumpall で出力されたクラスター全体の SQL が入っています。ダウンロードしたファイルはそのまま触らずに置いておいてください。 Zenavo は Zeabur の .zip バックアップのほか、通常の .sql や .sql.gz もそのままアップロードできます。

2. Zenavo で同じメジャーバージョンの空のデータベースを作る

移行先の Zenavo プロジェクトで サービスを追加 → データベース → PostgreSQL をクリックし、Zeabur と同じメジャーバージョンを選んでデプロイします。

気をつける点は3つです。

  • まずはメジャーバージョンを揃える:Zenavo は新しいメジャーバージョン(例:PG 18)のクラスターバックアップを古いバージョン(例:PG 17)へ復元することをブロックします。まずは同じバージョンで移行し、必要ならあとからアップグレードしてください。
  • 移行先のデータベースは空のままにしておく:起動時に自動でテーブルを作るアプリを先に動かさないでください。すでにテーブルが存在すると、クラスターバックアップの復元がエラーになります。
  • 拡張機能を確認する:PostGIS や pgvector などの拡張機能を使っている場合は、移行先のイメージに対応拡張が含まれているか確認します。

3. バックアップをアップロードして復元する

新しく作成した PostgreSQL サービスの バックアップと復元(Backup & Restore) タブを開き、手順 1 で Zeabur からダウンロードしたファイルをアップロードして復元を実行します。

Zeabur のバックアップは pg_dumpall のクラスターダンプであるため、Zenavo は復元時に自動で次の変換を行います(詳しくはバックアップのアップロードをご覧ください)。

  • ダンプ内のアプリケーション用データベースを、対象サービスのデータベースへ復元します。
  • バックアップ内で使われているロールを作成し、パスワードと行レベルセキュリティ(RLS)ポリシーを引き継ぎます。
  • 安全のため、Zeabur の旧 root スーパーユーザーはスーパーユーザー権限なし・ログイン不可のロールに降格しつつ、テーブルやオブジェクトの所有権はそのまま維持します。
  • システムデータベースの template1 と postgres は自動でスキップします。

1つのクラスターバックアップにシステム以外のアプリケーション用データベースが複数含まれている場合はエラーになるため、分割が必要です(ほとんどの Zeabur プロジェクトは1つだけなので、そのままアップロードできます)。

拡張機能の不足などで復元が途中で失敗した場合は、中途半端にテーブルが残ったデータベースに重ねて再実行せず、一度サービスを削除して新しい空の PostgreSQL を作り直してから復元してください。

4. テーブルと行数を確認する

復元が終わったら、PostgreSQL サービスの データベースビュー(Database View) を開くと、ブラウザ上から読み取り専用の SQL を実行してデータを確認できます。

まず、業務用のテーブルがすべて揃っているか確認します。

SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
  AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;

次に、主要なテーブル(ユーザーや注文など)について、正確な行数と最新レコードの日時を Zeabur 側と突き合わせます。

SELECT count(*) AS row_count, max(created_at) AS latest_created_at
FROM public.orders;

(統計情報の推定行数ではなく、count(*) で正確な件数を確認してください。)

5. アプリを接続して切り替える

同じプロジェクト内のアプリサービスで、データベース接続変数を新しい PostgreSQL サービスに向けます(サービス名が postgresql の場合)。

DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}

Zeabur の旧 root アカウントを直接書かず、Zenavo の新しいデータベースが公開する接続変数を使ってください(Zeabur で起きたセキュリティ事案を踏まえても、新しく生成されたパスワードに切り替える方が安全です)。

切り替え中にデータの取りこぼしをゼロにするには、次の順番で進めます。

  1. まず現在のバックアップを使って Zenavo 上で復元の予行演習を行い、アプリをつないでログイン・参照・書き込みが動くことを確認します。
  2. アクセスが少ない時間帯を選び、Zeabur 側のアプリ(および定期ジョブやキューワーカー)を一時停止して、旧データベースに新しい書き込みが入らないようにします。
  3. Zeabur で最終バックアップを取得し、Zenavo の空の PostgreSQL サービスへ復元します。
  4. Zenavo 側のアプリを起動し、ドメインの DNS を切り替えます。

よくある質問

復元時に「データベースが空ではありません(database is not empty)」というエラーが出ます 復元より先にアプリが新しいデータベースへ接続し、Prisma や TypeORM などの自動マイグレーションでテーブルを作ってしまった状態です。一度アプリを止め、PostgreSQL サービスを作り直して、先にバックアップを復元してからアプリを起動してください。

復元は成功したのに、アプリで permission denied やログイン失敗が出ます Zeabur のバックアップに含まれる旧 root スーパーユーザーはログイン不可に設定されます。アプリの DATABASE_URL を Zenavo の ${POSTGRESQL_CONNECTION_STRING}(標準の postgres ユーザーと新しいパスワード)に変更してください。

Zeabur からダウンロードした .sql.gz ファイルが展開できません Zeabur のエクスポート時のファイル名の仕様で、実体は .zip アーカイブになっています。名前を変えたり手元で展開したりせず、そのまま Zenavo の バックアップと復元 にアップロードすれば自動で判別されます。

データの復元と確認が終わったら、Zenavo の バックアップと復元 で定期バックアップも有効にしておきましょう。プロジェクト全体の移行手順は Zeabur からの移行ガイドをご覧ください。