TECH BLOG
技術ブログ

ARTICLE

  • 2023-08-20 PostgreSQL

    PostgreSQL 15 で廃止となった排他的バックアップについて

排他的バックアップと非排他的バックアップ

PostgreSQL 15 でオンライン物理バックアップを取得する方法の一つである排他的バックアップ方式が廃止となりました。
公式ドキュメントの用語を用いると、低レベルAPIを使用したベースバックアップに該当するものです。
PostgreSQL 14 のドキュメントへのリンクを下記に記載します。

【PostgreSQL 14 ドキュメント - 25.3.3. 低レベルAPIを使用したベースバックアップの作成 -】
https://www.postgresql.jp/document/14/html/continuous-archiving.html#BACKUP-LOWLEVEL-BASE-BACKUP

関数の変更

また、オンライン物理バックアップの開始と終了を行う関数についても、PostgreSQL 15 から変更されています。

バージョン 開始用の関数 終了用の関数
PostgreSQL 14 以前 pg_start_backup pg_stop_backup
PostgreSQL 15 以降 pg_backup_start pg_backup_stop

排他的バックアップと非排他的バックアップの主な相違点

非排他的バックアップは、排他的バックアップと比較して以下のような相違点があります。

  1. 終了用の関数を実行した結果をファイルに保存する必要がある。
  2. 開始用の関数を実行したセッションで、終了用の関数を実行する必要がある。

以降の説明では PostgreSQL 15 を前提としています。PostgreSQL 14 以前では pg_backup_start および pg_backup_stop 関数は、pg_start_backup 関数、pg_stop_backup 関数と読み替えてください。

1. 終了用の関数を実行した結果をファイルに保存する必要がある。

非排他的バックアップでは、終了用の関数である pg_backup_stop 関数の結果を、ファイルに保存する必要があります。
pg_backup_stop 関数は、3 つの列を持つレコードを返します。

pg_backup_stop ( [wait_for_archive boolean ] ) → record ( lsn pg_lsn, labelfile text, spcmapfile text )

この 2 番目の labelfile の内容を backup_label という名前のファイルに保存し、3 番目の spcmapfile の内容を tablespace_map という名前のファイルに保存する必要があります。
文章だけではピンとこないと思いますので、psql での手順の一例を下記に記載します。

-- 1. pg_backup_stop 関数の結果を受け取る一時テーブルを作成
CREATE TEMP TABLE backup_stop_result (lsn pg_lsn, labelfile TEXT, spcmapfile TEXT);

-- 2. pg_backup_stop の結果を一時テーブルに追加
INSERT INTO backup_stop_result SELECT * FROM pg_backup_stop();

-- 3. レコードの内容をファイルに格納するため出力形式を変更
¥pset tuples_only on
¥pset format unaligned

-- 4. labelfile の内容を backup_label に出力
¥o /tmp/backup_label
SELECT labelfile FROM backup_stop_result;
¥o

-- 5. spcmapfile の内容を tablespace_map に出力
¥o /tmp/tablespace_map
SELECT spcmapfile FROM backup_stop_result;
¥o

※上記の手順は一例ですので、一時テーブルを作成せずに実現する方法もあります。

排他的バックアップでは backup_label と tablespace_map の出力を自動でやっていてくれていたのですが、非排他的バックアップでは手動でやる必要があるため、どうしても手順が増えてしまいます。

注意点

注意点としては、backup_label と tablespace_map をデータベースクラスタ($PGDATA)直下に出力しないことが推奨となります。
PostgreSQL がリカバリする際に、最後のチェックポイントから WAL ファイルを利用してロールフォワードするのですが、データベースクラスタ直下に backup_label が存在する場合、その backup_label に記載のチェックポイントの位置からロールフォワードを行う挙動となります。
ロールフォワードに必要な WAL ファイルが存在しない(削除されている)場合、PostgreSQL はリカバリできず、起動処理がエラーとなってしまいます。
そのため、バックアップしたデータベースクラスタの直下には backup_label と tablespace_map は保存しておくべきですが、稼働中のデータベースクラスタの直下には backup_label と tablespace_map は配置しないようにした方が安全です。

2. 開始用の関数を実行したセッションで、終了用の関数を実行する必要がある。

排他的バックアップでは、開始用の関数と終了用の関数は別セッションで実行してもよかったのですが、非排他的バックアップでは同じセッションで実行する必要があります。
psql で実行している場合は、-c オプションを列挙することで実現できます。
手順の一例を下記に記載します。

psql -c "SELECT * FROM pg_backup_start('test', false);" \
    -c "\! tar cfvz /tmp/basebackup_15a.tar.gz ${PGDATA}" \
    -c "CREATE TEMP TABLE backup_stop_result (lsn pg_lsn, labelfile TEXT, spcmapfile TEXT);" \
    -c "INSERT INTO backup_stop_result SELECT * FROM pg_backup_stop()" \
    -c "\pset tuples_only on" \
    -c "\pset format unaligned" \
    -c "\o /tmp/backup_label " \
    -c "SELECT labelfile FROM backup_stop_result; " \
    -c "\o" \
    -c "\o /tmp/tablespace_map " \
    -c "SELECT spcmapfile FROM backup_stop_result; " \
    -c "\o" 

1 行目でバックアップの開始関数を実行し、2 行目でデータベースクラスタのバックアップ処理を行っています。
3 行目でバックアップの終了関数を実行しています。
※ 3 行目以降は「1. 終了用の関数を実行した結果をファイルに保存する必要がある」で挙げた手順と同じです。

pg_exclusive_backup 拡張モジュール

PostgreSQL 15 でも排他的バックアップを利用したい、という人向けに pg_exclusive_backup という拡張モジュールが公開されています。
ただ、pg_exclusive_backup の GitHub ( https://github.com/MasaoFujii/pg_exclusive_backup ) には「特別な理由がなければ非排他的バックアップを利用してください」という説明があります(下記に抜粋)。

It's recommended that a non-exclusive backup is used unless you have special reason why an exclusive backup needs to be used.

PostgreSQL 16 以降でも pg_exclusive_backup 拡張モジュールが使えるとは限りませんし、基本的には非排他的バックアップを利用するのが良さそうです。

まとめ

今回は PostgreSQL 15 で廃止された排他的バックアップについてまとめました。
PostgreSQL 15 以降へバージョンアップするなどの理由で、バックアップの方式を排他的バックアップから非排他的バックアップに変更する場合、排他的バックアップと非排他的バックアップの相違点をしっかりと理解しておくのが推奨となります。

CATEGORY

ARCHIVE

PostgreSQLの
ハイパフォーマンスチューニングのご相談は
株式会社インサイトまで
お気軽にお問い合わせください。

CONTACT