PostgreSQLのオンラインバックアップとリカバリ¶
2016/3/3¶
PostgreSQLはオンラインバックアップに対応している。
ということで、オンラインバックアップをしてみたのと、リカバリまで試して記録とまとめ。
バックアップの方式としてはpg_dumpコマンドを用いたものもオンラインでできるが、WALアーカイブを用いたバックアップを試してみることにした。
簡単に仕組みを説明
- Postgesはデータベースの更新時、トランザクションのログ、WALを残してから実行される。
- そうすることで、データベースがクラッシュしてもWALを追うことで、リカバリできる仕組みになっている。
- WALアーカイブとは、一定のタイミングでそのWALを別の場所にアーカイブしておく仕組み。
- 例えば、データベースの実態が入っているディスクとは別のディスクにWALアーカイブを出力しておけば、最悪データベースが入っているディスクが完全に破損しても、あるポイントまでリカバリできるようになる。
ちなみに以下はPostgres Ver.9.4で検証している。
Postgresの設定¶
postgresql.conf¶
# walアーカイブを出力する設定
wal_level = archive
# walアーカイブを出力するときに実行するコマンド。WALをcpコマンドで所定の場所にコピーしている。
# %pはwalファイル名、%fはwalアーカイブファイル名が自動で入力される
archive_command = 'cp %p /var/lib/pgsql/9.4/wal/%f'
# 同時に稼動するWAL送信プロセスの最大値
max_wal_senders = 1
ph_hba.conf¶
# ローカルのpostgresユーザにレプリケーション権限を与える。
local replication postgres peer
バックアップ¶
バックアップの流れ
- ベースバックアップを定期的に取る
- WALアーカイブを安全な場所に出力しておく
ベースバックアップ¶
ベースバックアップとは、postgresの設定やら実際のデータベースの中身やらをまるまるバックアップする仕組み。
以下のコマンドで実行できる(※)。
pg_basebackup -D [dirpath] -F t -x -z
※Ver.9.1からこのコマンドが使えるとのこと。
コマンドはデータベース管理ユーザ(デフォルトだとpostgres)で実行すること。
オプションの説明¶
-D :ベースバックアップ出力先パスを指定。出力先は空でなければならない。
ディレクトリが存在しなければ作ってくれる。
-F t :出力する形式。tはtarで出力する。
-x :ベースバックアップ処理中、データベースが更新された際もファイルシステム上の
ファイルは更新しないようにする。出力中はメモリ上で頑張る。
(そうすることで、出力ファイルが変な状態になることを防ぐ)
-z :gzipで圧縮した状態にする
こちらのコマンドを実行すると、base.tar.gzというファイルが生成される。 それを展開すると以下のものが入っている。
-rw-------. 1 postgres postgres 4 3月 1 21:49 PG_VERSION
-rw-------. 1 postgres postgres 206 3月 2 21:01 backup_label
drwx------. 6 postgres postgres 50 3月 1 21:50 base
drwx------. 2 postgres postgres 4096 3月 2 21:01 global
drwx------. 2 postgres postgres 17 3月 1 21:49 pg_clog
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_dynshmem
-rw-------. 1 postgres postgres 4218 3月 1 21:50 pg_hba.conf
-rw-------. 1 postgres postgres 1636 3月 1 21:49 pg_ident.conf
drwx------. 2 postgres postgres 6 3月 1 21:50 pg_log
drwx------. 4 postgres postgres 37 3月 1 21:49 pg_logical
drwx------. 4 postgres postgres 34 3月 1 21:49 pg_multixact
drwx------. 2 postgres postgres 17 3月 2 20:40 pg_notify
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_replslot
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_serial
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_snapshots
drwx------. 2 postgres postgres 6 3月 2 20:40 pg_stat
drwx------. 2 postgres postgres 6 3月 2 21:00 pg_stat_tmp
drwx------. 2 postgres postgres 17 3月 1 21:49 pg_subtrans
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_tblspc
drwx------. 2 postgres postgres 6 3月 1 21:49 pg_twophase
drwx------. 3 postgres postgres 58 3月 2 21:01 pg_xlog
-rw-------. 1 postgres postgres 88 3月 1 21:49 postgresql.auto.conf
-rw-------. 1 postgres postgres 21331 3月 1 21:50 postgresql.conf
postgresを触ったことがある人であれば、まるまるバックアップされていることがわかるかと。
WALアーカイブ¶
WALアーカイブ出力先を覗いてみると以下のようなファイルが出力されている。
-rw-------. 1 postgres postgres 16777216 3月 1 21:59 000000010000000000000001
-rw-------. 1 postgres postgres 16777216 3月 2 03:56 000000010000000000000002
-rw-------. 1 postgres postgres 16777216 3月 2 21:01 000000010000000000000003
-rw-------. 1 postgres postgres 16777216 3月 2 21:01 000000010000000000000004
-rw-------. 1 postgres postgres 302 3月 2 21:01 000000010000000000000004.00000028.backup
デフォルトだと、WALが16MBごとにアーカイブを残すようになっている。
なので、16MBのファイルがいっぱいある。
「〜.00000028.backup」について、これはベースバックアップ実行時に生成されるファイル。
バックアップ履歴ファイルと言い、チェックポイント等、ベースバックアップ取得時の情報が入っている。
中身は以下のとおり。
START WAL LOCATION: 0/4000028 (file 000000010000000000000004)
STOP WAL LOCATION: 0/40000B8 (file 000000010000000000000004)
CHECKPOINT LOCATION: 0/4000028
BACKUP METHOD: streamed
BACKUP FROM: master
START TIME: 2016-03-02 21:01:03 JST
LABEL: pg_basebackup base backup
STOP TIME: 2016-03-02 21:01:05 JST
〜.backの前半部分と同じファイル名の 000000010000000000000004
が一番最初に必要なファイルとなる。
000000010000000000000004
とそれ以降生成されるWALアーカイブをリカバリのために取っておく必要がある。
その前のファイルは消してしまっても問題なし。
(といっても、余裕があれば取っておいたほうが安心。)
まとめると、リカバリに必要なのは以下のファイル。
- ベースバックアップ(base.tar.gz)
- バックアップ履歴ファイル(000000010000000000000004.00000028.backup)
- .backupが付いている、元のファイル名以降のWALアーカイブ
(000000010000000000000004以降のWALアーカイブ)
リカバリ¶
リカバリの流れ
- postgresのサービスを停止する
- データベースクラスタを消去する
- ベースバックアップファイルをデータベースクラスタの場所に展開する
- ベースバックアップの中身に入っているWALは一旦削除する
- WALアーカイブを適当な場所に配置する
- recovery.confファイルを作成する
- postgresのサービスを起動する
postgresのサービス停止¶
RHEL7系のsystemdであれば以下のとおり。
systemctl stop postgresql-9.4.service
データベースクラスタの消去¶
データベースクラスタとはデータベースが入ってる場所。
デフォルトだと、 /var/lib/pgsql/[バージョン]/data
この中身をまるまる削除する。
(ディスクに余裕があれば、削除ではなく別の場所に移動する等のほうが良い)
rm -rf /var/lib/pgsql/9.4/data/*
ベースバックアップファイルの展開¶
データベースクラスタのディレクトリ内にベースバックアップを展開します。
tar xvf base.tar.gz
ベースバックアップの中のWALの削除¶
ベースバックアップ取得時のWALは最新のものではないため削除する。
(こちらもディスクに余裕があれば、削除ではなく別の場所に移動する等のほうが良い)
pg_xlogの中身を削除。
rm -rf /var/lib/pgsql/9.4/data/pg_xlog/*
WALアーカイブを適当な場所に配置¶
WALアーカイブの配置はこの後の設定で場所を指定するので、どこでも良い。
postgresユーザが読み取り権限をもっている場所である必要あり。
recovery.confファイルの作成¶
データベースクラスタの場所に作成。
vim /var/lib/pgsql/9.4/data/recovery.conf
recovery.confの中身
# 以下の1行のみでOK
restore_command = 'cp /tmp/wal/%f %p'
★WALアーカイブが置いてある場所はここで指定する。
上記の場合、WALアーカイブの配置先として"/tmp/wal"を指定している。
postgresのサービス起動¶
あとはサービスを起動するだけとなる。
systemctl start postgresql-9.4.service
postgresのサービス起動時にWALを読み込み、自動でリカバリをしてくれる。
postgresのログを見たところ以下の通りログが出力されていた。
2016-03-02 21:39:20.008 JST 2713 56d6def8.a99-1 0 LOG: データベースシステムは中断されました: 今回は 2016-03-02 21:01:03 JST までは到達しています
2016-03-02 21:39:20.008 JST 2713 56d6def8.a99-2 0 LOG: 見つからなかった WAL ディレクトリ "pg_xlog/archive_status" を作成しています ...
2016-03-02 21:39:20.245 JST 2713 56d6def8.a99-3 0 LOG: アーカイブリカバリを開始しています
2016-03-02 21:39:20.269 JST 2713 56d6def8.a99-4 0 LOG: ログファイル"000000010000000000000004"をアーカイブからリストアしました
2016-03-02 21:39:20.352 JST 2713 56d6def8.a99-5 0 LOG: 0/4000090のREDOを開始します
2016-03-02 21:39:20.436 JST 2713 56d6def8.a99-6 0 LOG: 0/40000B8 でリカバリー状態の整合が取れました
cp: `/tmp/wal/000000010000000000000005' を stat できません: そのようなファイルやディレクトリはありません
2016-03-02 21:39:20.441 JST 2713 56d6def8.a99-7 0 LOG: 0/40000B8のREDOが終わりました
2016-03-02 21:39:20.464 JST 2713 56d6def8.a99-8 0 LOG: ログファイル"000000010000000000000004"をアーカイブからリストアしました
cp: `/tmp/wal/00000002.history' を stat できません: そのようなファイルやディレクトリはありません
2016-03-02 21:39:20.468 JST 2713 56d6def8.a99-9 0 LOG: 選択された新しいタイムラインID: 2
cp: `/tmp/wal/00000001.history' を stat できません: そのようなファイルやディレクトリはありません
2016-03-02 21:39:20.597 JST 2721 56d6def8.aa1-1 0 (postgres, postgres, [local], [unknown])FATAL: データベースシステムは起動しています
2016-03-02 21:39:21.119 JST 2713 56d6def8.a99-10 0 LOG: アーカイブリカバリが完了しました
2016-03-02 21:39:21.598 JST 2722 56d6def9.aa2-1 0 (postgres, postgres, [local], [unknown])FATAL: データベースシステムは起動しています
2016-03-02 21:39:22.003 JST 2713 56d6def8.a99-11 0 LOG: MultiXact member wraparound protections are now enabled
2016-03-02 21:39:22.008 JST 2711 56d6def7.a97-3 0 LOG: データベースシステムの接続受付準備が整いました。
2016-03-02 21:39:22.008 JST 2724 56d6defa.aa4-1 0 LOG: 自動バキュームランチャプロセス
リカバリ、つまりWALからREDOしているのがわかるかと。
以上で終わり。結構簡単。