- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- PostgreSQL/解析/pg_rewind へ行く。
pg_rewind †
タイムライン分岐したデータベースサーバを同期させるツール。例えば、レプリケーションでプライマリ、スタンバイとあって、プライマリが何らかの障害等で停止し、スタンバイがプライマリに昇格した時、スタンバイは新しいタイムラインでシステムを継続する。この後、プライマリを新しいスタンバイとして組み込みたい場合、pg_rewindコマンドを使用すると、新しいタイムラインのスタンバイ(新プライマリ)に同期させることができる。リカバリの方法としてpg_basebackupコマンドがあるが、こちらはデータベースディレクトリを丸々複製するのに対し、pg_rewindは差分データのみ同期させることで、データ転送量を抑えることができ、復旧時間の短縮化することができる。(更新内容にもよるが、データベースクラスタサイズが大きいシステムではpg_rewindがリカバリ時間の短縮をすることができるだろう)。
pg_rewind --debug -D primary/pgdata -P --source-server="host=localhost dbname=postgres port=5433" # source-serverとは、複製元となるサーバのことである。 # つまり新しく組み込もうとしているサーバを同期させるサーバである。
pg_rewindは、差分ファイル転送と巻き戻しを行うだけであり、コマンド実行以降は起動時リカバリ処理でソースサーバに追従する。復旧までに時間がかかり、ソースサーバ上のWALが既にアーカイブされて退避されていた場合、起動時リカバリ処理に失敗してしまうため、起動前にアーカイブWALをターゲットサーバに転送しておく必要がある。
例:ソースサーバ上のWALがアーカイブされてしまい、ターゲットサーバの起動時リカバリ処理で失敗してしまう
LOCATION: libpqrcv_receive, libpqwalreceiver.c:757 LOG: 00000: started streaming WAL from primary at 0/4000000 on timeline 2 LOCATION: WalReceiverMain, walreceiver.c:409 FATAL: XX000: could not receive data from WAL stream: ERROR: requested WAL segment 000000020000000000000004 has already been removed
pg_rewindの実行条件 †
pg_rewindを実行するには、正常停止している必要がある。
よって障害等でプロセスが突然ダウンしてしまった場合、一度インスタンスを起動し正常停止させる。
pg_rewindの動作概要 †
- コピー元のソース一覧を取得し、コピー元にないファイルがコピー先にある場合、コピー先のファイルを削除する。
- pg_rewindは、fork前の最後のチェックポイント以降のWALレコードを辿り、更新されたブロック情報を取得する。
- コピー元から、更新ブロックされたブロック、ファイルなどを取得する。
- forkの箇所まで巻き戻した後は、インスタンス起動し、rewindで取得したWAL(コピー元になり場合はアーカイブからリストアすることもある)を再生する。
ソースサーバ上のファイル一覧取得 †
ソースサーバのファイル一覧を知るために、ソースサーバ上で以下のSQLが実行される。
WITH RECURSIVE files (path, filename, SIZE, isdir) AS ( SELECT '' AS path, filename, SIZE, isdir FROM (SELECT pg_ls_dir('.', TRUE, FALSE) AS filename) AS fn, pg_stat_file(fn.filename, TRUE) AS this UNION ALL\n" SELECT parent.path || parent.filename || '/' AS path, fn, this.size, this.isdir\n" FROM files AS parent,\n" pg_ls_dir(parent.path || parent.filename, true, false) AS fn, pg_stat_file(parent.path || parent.filename || '/' || fn, true) AS this WHERE parent.isdir = 't' ) SELECT path || filename, size, isdir, pg_tablespace_location(pg_tablespace.oid) AS link_target FROM files LEFT OUTER JOIN pg_tablespace ON files.path = 'pg_tblspc/' AND oid::text = files.filename;
ただし、以下のリソースは対象外である。
# 対象外のディレクトリ pg_stat_tmp pg_replslot pg_dynshmem pg_notify pg_serial pg_snapshots pg_subtrans # 対象外のファイル postgresql.auto.conf.tmp current_logfiles.tmp backup_label tablespace_map postmaster.pid postmaster.opts
デバッグ出力の例 †
connected to server fetched file "global/pg_control", length 8192 fetched file "pg_wal/00000002.history", length 41 Source timeline history: Target timeline history: 1: 0/0 - 0/0 servers diverged at WAL location 0/301F968 on timeline 1 rewinding from last common checkpoint at 0/301F8F8 on timeline 1 reading source file list entry "postmaster.opts" excluded from source file list entry "postmaster.pid" excluded from source file list entry "global/pg_internal.init" excluded from source file list entry "pg_notify/0000" excluded from source file list entry "pg_subtrans/0000" excluded from source file list entry "base/12630/pg_internal.init" excluded from source file list reading target file list entry "pg_notify/0000" excluded from target file list entry "pg_subtrans/0000" excluded from target file list entry "postmaster.opts" excluded from target file list reading WAL in target backup_label.old (COPY) base/1/12465_fsm (COPY) base/1/12465_vm (COPY) base/1/12470_fsm (COPY) ... pg_stat/global.stat (REMOVE) need to copy 51 MB (total source directory size is 70 MB) getting file chunks received chunk for file "backup_label.old", offset 0, size 224 0/53164 kB (0%) copied received chunk for file "base/1/12465_fsm", offset 0, size 24576 received chunk for file "base/1/12465_vm", offset 0, size 8192 received chunk for file "base/1/12470_fsm", offset 0, size 24576 received chunk for file "base/1/12470_vm", offset 0, size 8192 ... received chunk for file "base/12630/16384", offset 50008192, size 1000000 ... received chunk for file "pg_wal/000000020000000000000003", offset 16000000, size 777216 received chunk for file "pg_xact/0000", offset 0, size 8192 received chunk for file "postgresql.auto.conf", offset 0, size 88 received chunk for file "postgresql.conf", offset 0, size 23809 received chunk for file "recovery.done", offset 0, size 274 received chunk for file "base/12630/16384", offset 8192, size 49152 53164/53164 kB (100%) copied creating backup label and updating control file syncing target data directory
参考
一度に転送される最大のデータサイズは、size 1000000となっている。ざっと1MB程度である。
ファイル転送の内部動作 †
- pg_rewindで転送するファイルに関する情報を一時テーブルでソースサーバ上に作成する。
CREATE TEMPORARY TABLE fetchchunks(path text, begin int8, len int4);
- 続いて、COPYコマンドで、path、begin、lenの情報を各転送対象ソースに対して求める。
COPY fetchchunks FROM STDIN;
- 最後は、SELECT分を発行し、実データを取得する。
SELECT path, begin, pg_read_binary_file(path, begin, len, true) AS chunk FROM fetchchunks;