PostgreSQLのWAL(Write Ahead Log)についてまとめます。WALはデータベースに対する更新操作が記載されたログで、ストリーミングレプリケーションやPITR(Point In Time Recovery)で使用されます。
- PostgreSQL インストール
- PostgreSQL データベースの作成
- PostgreSQL contribモジュールの使い方
- PostgreSQL パラメタの設定方法
- PostgreSQL ベンチマークツールの紹介
- PostgreSQL WAL(Write Ahead Log)の基本説明 (いまここ)
- PostgreSQL バックアップとリストア
- PostgreSQL PITR(Point In Time Recovery)基本概念の説明
- PostgreSQL PITR(Point In Time Recovery)操作方法の説明
- PostgreSQL PITR(Point In Time Recovery)タイムライン操作
- PostgreSQL ストリーミングレプリケーションの最小構成
- PostgreSQL ストリーミングレプリケーションのパラメタ説明
- PostgreSQL ストリーミングレプリケーションの障害復旧
- PostgreSQL ストリーミングレプリケーションの多段構成
- PostgreSQL ストリーミングレプリケーションのDR向け設定
- PostgreSQL ストリーミングレプリケーションのコンフリクト
- PostgreSQL 自動バキューム(AUTO VACUUM)
- PostgreSQL HOT(Heap Only Tuple)
- PostgreSQL インデックスのメンテナンス
- PostgreSQL 統計情報の更新
- PostgreSQL 実行計画
- PostgreSQL スロークエリの調査方法
WALのファイル確認
WALは更新操作が記録されるログです。WALの動作確認を行うために、何らかの更新操作を行います。
pgbenchを用いて簡単な更新操作を行う例を以下に示します。
createdb test /usr/pgsql-13/bin/pgbench -i test /usr/pgsql-13/bin/pgbench -c 5 -t 100 test
更新操作を行うと、pg_wal配下に連番のファイルが作成されます。これがWALです。
[postgres@centos10 ~]$ ls -l /var/lib/pgsql/13/data/pg_wal/ total 32768 -rw------- 1 postgres postgres 16777216 Dec 15 12:02 000000010000000000000001 -rw------- 1 postgres postgres 16777216 Dec 15 12:03 000000010000000000000002 drwx------ 2 postgres postgres 6 Dec 15 12:00 archive_status [postgres@centos10 ~]$
WALはバイナリファイルです。これを閲覧するには、pg_waldumpと呼ばれるツールを使用します。
pg_waldumpを使用するとLSN(Log Sequence Number)を調べる事ができます。LSNはログに対して付与される番号で、PITR(Point In Time Recovery)をする時は、どのLSNまでをリカバリするかを指定する事ができます。
[postgres@centos10 ~]$ /usr/pgsql-13/bin/pg_waldump /var/lib/pgsql/13/data/pg_wal/000000010000000000000001 rmgr: XLOG len (rec/tot): 114/ 114, tx: 0, lsn: 0/01000028, prev 0/00000000, desc: CHECKPOINT_SHUTDOWN redo 0/1000028; tli 1; prev tli 1; fpw true; xid 0:3; oid 12000; multi 1; offset 0; oldest xid 3 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 0; shutdown rmgr: XLOG len (rec/tot): 30/ 30, tx: 1, lsn: 0/010000A0, prev 0/01000028, desc: NEXTOID 20192 rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/010000C0, prev 0/010000A0, desc: FPI , blkref #0: rel 1663/1/6117 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/01000150, prev 0/010000C0, desc: FPI , blkref #0: rel 1664/0/6115 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/010001E0, prev 0/01000150, desc: FPI , blkref #0: rel 1664/0/6114 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/01000270, prev 0/010001E0, desc: FPI , blkref #0: rel 1663/1/6113 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/01000300, prev 0/01000270, desc: FPI , blkref #0: rel 1663/1/6112 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/01000390, prev 0/01000300, desc: FPI , blkref #0: rel 1663/1/6111 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/01000420, prev 0/01000390, desc: FPI , blkref #0: rel 1663/1/6110 blk 0 FPW rmgr: XLOG len (rec/tot): 49/ 137, tx: 1, lsn: 0/010004B0, prev 0/01000420, desc: FPI , blkref #0: rel 1663/1/3351 blk 0 FPW
WALバッファとWAL
WALは高速な書き込みを実現するために、メモリに書き込んでから非同期でディスクに書き込みます。メモリに書き込まれた領域はWALバッファと呼ばれます。
特段のチューニングがおこなれていない場合は、デフォルト設定の200ms間隔でWAL writterというプロセスがメモリ上のWALバッファをディスクに書き込みます。その他、クラッシュが起きた時にデータ不整合が起きないよう、様々なタイミングでディスクへの書き込みを行います。書き込みを行うタミングを以下に整理します。
- wal writer 定期実行
- COMMIT 実行時
- CHECKPOINT 実行時
- VACUUM 実行時
- WALバッファ溢れ
- 共有バッファ溢れ
WALのスイッチ
WALは16MB固定です。16MBを超えると次のWALに書き込みをするようになります。
例えば、000000010000000000000003への書き込みを続けたところ、このファイルが16MBを超過しました。その場合は、次は000000010000000000000004に書き込むようになります。
現在、どのWALへ書き込みを行なっているかはpg_current_wal_lsn()関数とselect pg_walfile_name()関数を組み合わせて調査する事ができます。
pg_current_wal_lsn()は、LSNの現在の値を返す関数です。
[postgres@centos10 ~]$ psql -c "SELECT pg_current_wal_lsn()" pg_current_wal_lsn -------------------- 0/3550818 (1 row)
pg_walfile_name()は引数にLSNを与える関数で、LSNがどのWALに所属するかのファイル名を返します。
[postgres@centos10 ~]$ psql -c "SELECT pg_walfile_name(pg_current_wal_lsn())" pg_walfile_name -------------------------- 000000010000000000000003 (1 row)
WALのスイッチは16MBを超えた時だけでなく、手動で行う事もできます。例えば、select pg_switch_wal()関数を使用するとWALをスイッチさせる事ができます。また、バックアップを取得する時のpg_start_back()関数でもスイッチが実施されます。
[postgres@centos10 ~]$ psql << EOF > \x > SELECT pg_walfile_name(pg_current_wal_lsn()); > select pg_switch_wal(); > SELECT pg_walfile_name(pg_current_wal_lsn()); > EOF Expanded display is on. -[ RECORD 1 ]---+------------------------- pg_walfile_name | 000000010000000000000003 -[ RECORD 1 ]-+---------- pg_switch_wal | 0/355D700 -[ RECORD 1 ]---+------------------------- pg_walfile_name | 000000010000000000000004
WAL Level
WALはどの程度詳細なログを出力するかを指定するwal_levelと呼ばれる設定があります。デフォルトではreplicaですが、ロジカルレプリケーションを行う場合はlogicalに変更し、最小限のログで充分な場合はminimalに変更する事もできます。
古いバージョンのPostgreSQLでは、wal_levelのデフォルト設定はminimalです。
wal_levelの設定をまとめると以下の通りです。(参照「19.5. Write Ahead Log」)
wal_level | 挙動 |
---|---|
minimal | クラッシュや突然のシャットダウンから復旧するのに充分なログを記録する。ログを減らし高速化を図る時に使用 |
replica | ストリーミングレプリケーションを行うのに充分なログを記録する |
logical | ロジカルレプリケーションを行うのに充分なログを記録する。ログの量が増える事に注意 |
wal_levelをminimalとした場合は、以下操作がWALに記録されなくなる事で高速化を図ります。
- ALTER … SET TABLESPACE
- CLUSTER
- CREATE TABLE
- REFRESH MATERIALIZED VIEW (without CONCURRENTLY)
- REINDEX
- TRUNCATE
wal_levelをlogicalとした場合は、ロジカルチェンジセットをWALから取り出すのに必要な情報が追加される。WALの量が増える事に注意。特に、多数のテーブルがREPLICA IDENTITY FULLと設定されていて、多くのUPDATEとDELETE文が実行される場合は、ログ増量の傾向が顕著になります。
アーカイビング
パラメタ解説
アーカイビングはWALを別ディレクトリにコピーする機能です。コピー先をNSFのような共有領域にしておけば、バックアップからのロールフォワードやPITR(Pint In Time Recovery)で使用する事ができます。
アーカイビングに必要なパラメタを以下にまとめます。
パラメタ | 説明 |
---|---|
archive_mode | アーカイビングを有効にするか否かの設定。wal_levelがminimalの場合は有効化できない事に注意。 |
archive_command | アーカイブ先を指定するコマンド。「cp -p %p /nfs/%f」のようにコピーを行うコマンドを指定します。%p, %fはそれぞれWALとコピー先が格納される変数です。 |
archive_timeout | アーカイビングを試みるタイムアウト時間です。推奨値は60秒程度とされ、もし、それ以上に短い間隔を指定し素早いWAL転送を行いたいならばアーカイビングではなくストリーミングを行う事が推奨されています。 |
正常系 動作確認
アーカイブの出力先ディレクトリを作成します。
NFSサーバの構築方法については説明を省略します。
mkdir -p /nfs/postgres/wal chown -R postgres:postgres /nfs/postgres
postgresql.confを以下のように編集します。
# vi /var/lib/pgsql/13/data/postgresql.conf <omitted> archive_mode = on archive_command = 'cp -p %p /nfs/postgres/wal/%f' archive_timeout = 60
設定を反映させます。
systemctl restart postgresql-13.service
何らかの更新処理を発生され、WALを出力します。
createdb test /usr/pgsql-13/bin/pgbench -i test /usr/pgsql-13/bin/pgbench -c 5 -t 100000 test
アーカイブ領域にログがコピーされた事を確認します。
[root@centos10 ~]# ls -l /nfs/postgres/wal/ 合計 81920 -rw------- 1 postgres postgres 16777216 12月 18 18:02 000000010000000000000004 -rw------- 1 postgres postgres 16777216 12月 18 18:03 000000010000000000000005 -rw------- 1 postgres postgres 16777216 12月 18 18:04 000000010000000000000006 -rw------- 1 postgres postgres 16777216 12月 18 18:07 000000010000000000000007 -rw------- 1 postgres postgres 16777216 12月 18 18:09 000000010000000000000008 [root@centos10 ~]#
異常系 動作確認
NFSサーバに障害が発生した場合の挙動について考察します。まず、NFSサーバに障害を発生させます。
systemctl stop nfs-server.service
何らかの更新処理を発生され、WALを出力します。
/usr/pgsql-13/bin/pgbench -i test /usr/pgsql-13/bin/pgbench -c 5 -t 100000 test
wal_logが転送されたかどうかはpg_wal/archive_status/ディレクトリ上のファイルで管理されます。doneと書かれているのが転送が完了したファイルで、readyと書かれているのが転送可能な状態であるものの転送が完了していないものを表します。
[root@centos10 ~]# ls -l /var/lib/pgsql/13/data/pg_wal/archive_status/ 合計 0 -rw------- 1 postgres postgres 0 12月 18 18:09 000000010000000000000008.done -rw------- 1 postgres postgres 0 12月 18 18:14 000000010000000000000009.done -rw------- 1 postgres postgres 0 12月 18 18:14 00000001000000000000000A.done -rw------- 1 postgres postgres 0 12月 18 18:15 00000001000000000000000B.ready -rw------- 1 postgres postgres 0 12月 18 18:16 00000001000000000000000C.ready [root@centos10 ~]#
NFSサーバを復旧させてみます。
systemctl start nfs-server.service
archive_statusが全てdoneに変わります。
[root@centos10 ~]# ls -l /var/lib/pgsql/13/data/pg_wal/archive_status/ 合計 0 -rw------- 1 postgres postgres 0 12月 18 18:14 00000001000000000000000A.done -rw------- 1 postgres postgres 0 12月 18 18:15 00000001000000000000000B.done -rw------- 1 postgres postgres 0 12月 18 18:16 00000001000000000000000C.done -rw------- 1 postgres postgres 0 12月 18 18:17 00000001000000000000000D.done -rw------- 1 postgres postgres 0 12月 18 18:17 00000001000000000000000E.done -rw------- 1 postgres postgres 0 12月 18 18:18 00000001000000000000000F.done [root@centos10 ~]#
WALがNFS上に転送されている事を確認します。
[root@centos10 ~]# ls -l /nfs/postgres/wal/ 合計 229376 -rw------- 1 postgres postgres 16777216 12月 18 18:02 000000010000000000000004 -rw------- 1 postgres postgres 16777216 12月 18 18:03 000000010000000000000005 -rw------- 1 postgres postgres 16777216 12月 18 18:04 000000010000000000000006 -rw------- 1 postgres postgres 16777216 12月 18 18:07 000000010000000000000007 -rw------- 1 postgres postgres 16777216 12月 18 18:09 000000010000000000000008 -rw------- 1 postgres postgres 16777216 12月 18 18:14 000000010000000000000009 -rw------- 1 postgres postgres 16777216 12月 18 18:14 00000001000000000000000A -rw------- 1 postgres postgres 16777216 12月 18 18:15 00000001000000000000000B -rw------- 1 postgres postgres 16777216 12月 18 18:16 00000001000000000000000C -rw------- 1 postgres postgres 16777216 12月 18 18:17 00000001000000000000000D -rw------- 1 postgres postgres 16777216 12月 18 18:17 00000001000000000000000E -rw------- 1 postgres postgres 16777216 12月 18 18:18 00000001000000000000000F -rw------- 1 postgres postgres 16777216 12月 18 18:19 000000010000000000000010 -rw------- 1 postgres postgres 16777216 12月 18 18:19 000000010000000000000011 [root@centos10 ~]#