【準備】前準備
-
WALのアーカイブを有効化しておく
- postmasterなのでrestart必要
postgres=# SELECT name,setting,context FROM pg_settings WHERE name='archive_mode';
name | setting | context
--------------+---------+------------
archive_mode | off | postmaster
(1 row)
- 雑に
/tmp/archive
にコピーすることにする
archive_mode = on
archive_command = 'cp %p /tmp/archive/'
オンライン物理バックアップの仕組み
-
ベースバックアップ
pg_basebackup
コマンド-
低レベル関数
pg_start_backup
関数pg_end_backup
関数
-
WALファイル
pg_wal/
- アーカイブ
pgstartbackup関数の処理
-
流れ
-
共有メモリ上のステータスを「バックアップ中」にする
- 複数のベースバックアップが取得されないように
-
WALを新しいセグメントにスイッチする
- バックアップ中のWALは別のセグメント
-
チェックポイント発行、
backup_label
ファイルを書き出す- 開始時刻
- 特定用ラベル文字列
-
WALファイル名
- LSNをもとに特定
- LSN返却
-
チェックポイント処理の制御
SELECT pg_start_backup('label', false, false);
- 第一引数: バックアップラベル 特定用
-
第二引数: trueなら全力を出す デフォルトfalse
- falseの場合、
checkpoint_completion_target
にしたがって休み休み行う
- falseの場合、
-
第三引数: trueなら排他 デフォルトtrue
- 排他オプションはdeprecated
pgstopbackup関数の処理
-
流れ
- 共有メモリ上のステータスを元に戻す
backup_label
を読み込み、開始LSN位置を取得する- 当該LSNを含むWALレコードを読み出す
- WALをスイッチする (A)
- バックアップ履歴ファイルを書き出す (B)
- (A), (B)のWALファイルがアーカイブされるのを待つ
- LSN返却
- 公式
SELECT * FROM pg_stop_backup(false, true);
WALスイッチ
-
いつWALセグメントが切り替わるか
pg_start_backup
で一度スイッチpg_stop_backup
で一度スイッチ
- LSN取得
postgres=# SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn
---------------------------
0/16454E8
(1 row)
- LSNからWALファイル導出
postgres=# SELECT pg_walfile_name(pg_current_wal_insert_lsn());
pg_walfile_name
--------------------------
000000010000000000000001
(1 row)
postgres=# \! ls -lA pg_wal/
total 16388
-rw------- 1 postgres postgres 16777216 Feb 14 14:51 000000010000000000000001
drwx------ 2 postgres postgres 4096 Feb 14 14:49 archive_status
- ベースバックアップを開始してみる
postgres=# SELECT pg_start_backup('test');
pg_start_backup
-----------------
0/2000028
(1 row)
-
再度
pg_start_backup
を試みるとエラー- 共有メモリ上のステータスが「バックアップ中」の状態だから
postgres=# SELECT pg_start_backup('test2');
ERROR: a backup is already in progress
HINT: Run pg_stop_backup() and try again.
pg_start_backup
を実行したのでLSNが更新されている
postgres=# SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn
---------------------------
0/2000110
(1 row)
- WALがスイッチされている
postgres=# SELECT pg_walfile_name(pg_current_wal_insert_lsn());
pg_walfile_name
--------------------------
000000010000000000000002
(1 row)
postgres=# \! ls -lA pg_wal/
total 32772
-rw------- 1 postgres postgres 16777216 Feb 14 14:52 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Feb 14 14:52 000000010000000000000002
drwx------ 2 postgres postgres 4096 Feb 14 14:52 archive_status
- 1がアーカイブ準備できている
postgres=# \! ls -lA pg_wal/archive_status
total 0
-rw------- 1 postgres postgres 0 Feb 14 14:52 000000010000000000000001.ready
-
ベースバックアップ取得終了する
- ベースバックアップ取得中にスイッチしていたWALのLSNが返る
postgres=# SELECT pg_stop_backup();
NOTICE: all required WAL segments have been archived
pg_stop_backup
----------------
0/2000138
(1 row)
postgres=# \! ls -lA /tmp/archive
total 32772
-rw------- 1 postgres postgres 16777216 Feb 14 14:55 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Feb 14 14:56 000000010000000000000002
-rw------- 1 postgres postgres 323 Feb 14 14:56 000000010000000000000002.00000028.backup
postgres=# \! ls -lA pg_wal/
total 49160
-rw------- 1 postgres postgres 16777216 Feb 14 14:52 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Feb 14 14:56 000000010000000000000002
-rw------- 1 postgres postgres 323 Feb 14 14:56 000000010000000000000002.00000028.backup
-rw------- 1 postgres postgres 16777216 Feb 14 14:56 000000010000000000000003
drwx------ 2 postgres postgres 4096 Feb 14 14:56 archive_status
- ベースバックアップ取得中にスイッチしていたWALのファイル名取得
postgres=# SELECT pg_walfile_name('0/2000138');
pg_walfile_name
--------------------------
000000010000000000000002
(1 row)
- ベースバックアップ終了後のWAL書き込み先
postgres=# SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn
---------------------------
0/3000148
(1 row)
postgres=# SELECT pg_walfile_name(pg_current_wal_insert_lsn());
pg_walfile_name
--------------------------
000000010000000000000003
(1 row)
- 以降は3に書かれていく
backup_labelとバックアップ履歴ファイルの内容
-
backup_label
ファイルpg_start_backup()
実行後、pg_stop_backup()
実行前までデータベースクラスタに存在
postgres=# SELECT pg_start_backup('test');
pg_start_backup
-----------------
0/4000028
(1 row)
cat backup_label
START WAL LOCATION: 0/4000028 (file 000000010000000000000004)
CHECKPOINT LOCATION: 0/4000060
BACKUP METHOD: pg_start_backup
BACKUP FROM: master
START TIME: 2020-02-14 14:59:49 UTC
LABEL: test
START TIMELINE: 1
postgres=#
-
バックアップ履歴ファイル
STOP WAL LOCATION
がSTOP TIME
が追加される
Column: 並行したバックアップ取得の制御
-
第三引数falseで並行実行
- 並行でない排他実行はdeprecated
postgres=# SELECT pg_start_backup('test_exclusive', false, false);
pg_start_backup
-----------------
0/8000060
(1 row)
- データベースクラスタをcpやらtarやらでバックアップしてベースバックアップを取得
- のち、
pg_stop_backup(false)
する
postgres=# SELECT * from pg_stop_backup(false);
NOTICE: all required WAL segments have been archived
lsn | labelfile | spcmapfile
-----------+---------------------------------------------------------------+------------
0/6000138 | START WAL LOCATION: 0/6000060 (file 000000010000000000000006)+|
| CHECKPOINT LOCATION: 0/6000098 +|
| BACKUP METHOD: streamed +|
| BACKUP FROM: master +|
| START TIME: 2020-02-14 15:03:37 UTC +|
| LABEL: test_exclusive +|
| START TIMELINE: 1 +|
| |
(1 row)
-
この内容をベースバックアップに含める
labelfile
の内容:backup_label
ファイルspcmapfile
の内容:tablespace_map
ファイル
WALのアーカイブの流れ
-
*.ready
なやつがアーカイバプロセスによりarchive_command
によりアーカイブされる*.done
にリネームされる
postgres=# \! ls -lAR pg_wal/
pg_wal/:
total 49160
-rw------- 1 postgres postgres 16777216 Feb 14 15:03 000000010000000000000006
-rw------- 1 postgres postgres 326 Feb 14 15:03 000000010000000000000006.00000060.backup
-rw------- 1 postgres postgres 16777216 Feb 14 15:03 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Feb 14 15:03 000000010000000000000008
drwx------ 2 postgres postgres 4096 Feb 14 15:03 archive_status
pg_wal/archive_status:
total 0
-rw------- 1 postgres postgres 0 Feb 14 15:03 000000010000000000000006.00000060.backup.done
-rw------- 1 postgres postgres 0 Feb 14 15:03 000000010000000000000006.done
- psコマンドでアーカイバプロセスを確認すると、最後にアーカイブしたWALセグメントを確認できる
postgres-# \! ps axfww | grep postgres
67 pts/1 Ss+ 0:00 /usr/lib/postgresql/12/bin/psql
1094 pts/1 S+ 0:00 \_ sh -c ps axfww | grep postgres
1096 pts/1 S+ 0:00 \_ grep postgres
1 ? Ss 0:00 postgres
27 ? Ss 0:00 postgres: checkpointer
28 ? Ss 0:00 postgres: background writer
29 ? Ss 0:00 postgres: walwriter
30 ? Ss 0:00 postgres: autovacuum launcher
31 ? Ss 0:00 postgres: archiver last was 000000010000000000000006.00000060.backup
32 ? Ss 0:00 postgres: stats collector
33 ? Ss 0:00 postgres: logical replication launcher
87 ? Ss 0:00 postgres: postgres postgres [local] idle
- 詳細情報
postgres=# SELECT * FROM pg_stat_archiver;
-[ RECORD 1 ]------+-----------------------------------------
archived_count | 9
last_archived_wal | 000000010000000000000006.00000060.backup
last_archived_time | 2020-02-14 15:03:43.471038+00
failed_count | 9
last_failed_wal | 000000010000000000000001
last_failed_time | 2020-02-14 14:54:40.047857+00
stats_reset | 2020-02-14 14:49:42.366489+00
- failed : archive先ディレクトリを掘り忘れて失敗してたやつ
cp: cannot create regular file '/tmp/archive/': Not a directory
2020-02-14 14:54:40.047 UTC [31] LOG: archive command failed with exit code 1
2020-02-14 14:54:40.047 UTC [31] DETAIL: The failed archive command was: cp pg_wal/000000010000000000000001 /tmp/archive/
2020-02-14 14:54:40.047 UTC [31] WARNING: archiving write-ahead log file "000000010000000000000001" failed too many times, will try again later