7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PostgreSQL 9.6 で実装されたpg_start_backupのnon-exclusive modeについて

Last updated at Posted at 2017-05-22

PostgreSQL10のbeta1がリリースされましたね。

タイミングとしては、かなり今更ですが、PG96で実装されたpg_start_backupのnon-exclusiveモードを少し試していたので、備忘録として残します。

non-exclusive mode(非排他モード)とは

ざっくり言うと、これまでのexclusive modeとは以下の点で違いがあります。

  • 複数のバックアップを同時に取得できるようになった。
    • pg_start_backup中に別の人がpg_start_backupを実行できる。
  • Slaveに対してpg_start_backupが実行できるようになった。
    • これまではMasterにしか実行することができなかった。
    • (Masterからのバックアップ取得は以前からpg_basebackupコマンドでもできていたので、pg_start_backupに限った話という意味。)
  • pg_start_backup実行時、PGDATA配下にbackup_labelは作成されない。
    • これまではpg_start_backupで$PGDATA/backup_labelが作成され、pg_stop_backupで削除されていた。
    • backup_labelの情報はpg_stop_backup(false)実行時に出力される

という具合です。

non-exclusive modeでのバックアップ取得方法

以降の手順は対象がマスタ、スレーブのどちらであっても手順は同じです。

1. psqlで接続し、pg_start_backupを実行する。

non-exclusiveモードは第三引数(exclusive)を'false'にすることで使用できます。

postgres=# SELECT pg_start_backup('ore_no_backup', true, false);                                                                                    
 pg_start_backup 
-----------------
 0/2000060
(1 row)

2. ベースバックアップ取得

pg_start_backup実行後、cpコマンド等で$PGDATA配下のファイルをバックアップとして取得する。(従来と操作は変わらない。)

3. pg_stop_backupを実行する

pg_stop_backup(false)は、手順1と同じセッションで実行する。

postgres=# SELECT * FROM pg_stop_backup(false);                                                                                      
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
    lsn    |                           labelfile                           | spcmapfile 
-----------+---------------------------------------------------------------+------------
 0/6A055D0 | START WAL LOCATION: 0/2000028 (file 000000010000000000000002)+| 
           | CHECKPOINT LOCATION: 0/2000060                               +| 
           | BACKUP METHOD: streamed                                      +| 
           | BACKUP FROM: master                                          +| 
           | START TIME: 2017-05-20 10:20:38 JST                          +| 
           | LABEL: ore_no_backup                                         +| 
           |                                                               | 
(1 row)
カラム 概要
lsn pg_stop_backup実行時のWALの書き込み位置
labelfile backup_labelとして保存する内容
spcmapfile tablespace_mapとして保存する内容

このpg_stop_backupの結果から、リカバリに必要なアーカイブファイル等を確認することができます。

4. ベースバックアップ(2で取得済み)をリカバリするために以下のものを用意する。

  • アーカイブWAL
  • backup_label
  • recovery.conf

以降は例として、pg_stop_backup実行時までの状態にリストアする場合に必要なものを記載する。

4-1. アーカイブWALのバックアップを取得する。

ベースバックアップのリカバリに必要なアーカイブWALは、手順3のlabelfile,lsn(pg_stop_backup実行時の出力結果)から判断できる。今回だとSTART WAL LOCATIONで書かれている000000010000000000000002ファイルから、000000010000000000000006(lsn:0/6A055D0より判断)が対象になるので、以下のアーカイブWALをバックアップとして確保しておきます。

$ ll /tmp/back_arch/
total 81920
-rw------- 1 postgres postgres 16777216  5月 20 10:28 000000010000000000000002
-rw------- 1 postgres postgres 16777216  5月 20 10:28 000000010000000000000003
-rw------- 1 postgres postgres 16777216  5月 20 10:28 000000010000000000000004
-rw------- 1 postgres postgres 16777216  5月 20 10:28 000000010000000000000005
-rw------- 1 postgres postgres 16777216  5月 20 10:28 000000010000000000000006

LSNから対象のWALファイル名を調べるコマンドも用意されているので、それを使うのもありです。

$ psql postgres -c "SELECT pg_walfile_name('0/6A055D0')"
     pg_walfile_name      
--------------------------
 000000020000000000000006
(1 row)

ちなみに、PG96まではpg_xlogfile_name()でしたが、PG10からは上記のように関数名が変わっているので注意。

4-2. backup_labelを作成する。

こちらは、labelfileの内容をそのままコピペすればOKです。

$ cat $BACKUP/backup_label 
START WAL LOCATION: 0/2000028 (file 000000010000000000000002)
CHECKPOINT LOCATION: 0/2000060
BACKUP METHOD: streamed
BACKUP FROM: master
START TIME: 2017-05-20 10:20:38 JST
LABEL: ore_no_backup

PostgreSQLは起動時にbackup_labelの中身からリカバリを開始する場所を確認しているので、このファイルがないとバックアップをリストアすることはできません。

4-3. recovery.confを作成する。

restore_commandには、バックアップしたアーカイブWALのパスを指定しておきます。

$ cat $BACKUP/recovery.conf 
recovery_target_timeline='latest'
restore_command='cp /tmp/back_arch/%f %p'

おわり

以上で、バックアップで必要な操作(ベースバックアップ取得、リカバリに必要なファイルの用意)が全て完了しました。

ちなみに

コミュニティのwikiとかを見ると、将来的に従来のexclusiveモードは廃止の方針とのことです。
今のうちに新しいものは(若干古いが)ちゃんとキャッチアップしておこう!

あと、non-exclusiveモードはpsql の-cオプションで操作することができません。オンラインバックアップの操作(pg_start_backup/pg_stop_backup)は同じセッション内で行う必要があるので注意しよう。従来は-cオプションで操作できた。

追記(2017/6/21)

スタンバイでpg_stop_backup(false)を実行した場合、従来のものと挙動が異なるので注意!!!

  • マスタで実行した場合
    • WALをスイッチを行い、recoveryに必要なWALのアーカイブの完了を待つ。(従来通りの挙動)
  • スタンバイで実行した場合
    • WALのスイッチを行うが、マスタでのWALのアーカイブ完了は待たない。
    • archive_mode = always 設定時、スタンバイでのアーカイブも当然待たない。

つまり、スタンバイでpg_stop_backup(false)を実行した場合、アーカイブが失敗していてもstopは成功するため、ちゃんと必要なWALがアーカイブされているかチェックしないと***危険!!!***ということ。

これって仕様としてどうなんだ。。。せめてマニュアルには書いといてほしいな。

更に追記

PG10では、pg_stop_backupにもう一つパラメータが追加される。

pg_stop_backup(exclusive boolean [, wait_for_archive boolean ])

マニュアルを読むとWALアーカイブを待つかどうか制御できるものらしいが、ソースを見る限り、スタンバイで実行する場合は当然待たない。(というか待てない。)

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?