PostgreSQLの縁の下の力持ち、WALアーカイバプロセスを理解しよう!
やあ、みんな! PostgreSQLの運用、お疲れ様! 今日は、普段はあまり意識しないかもしれないけど、実はデータベースの安定稼働にめちゃくちゃ貢献してる「WALアーカイバプロセス」について、ちょっと深掘りしてみようと思うんだ。
「WALって何?」「アーカイバ?何のために?」って思った人もいるかもしれないね。大丈夫、最初はみんなそうだから。でも、これを知っておくと、バックアップ戦略がグッと楽になるし、いざという時の復旧もスムーズになるんだ。現場の先輩として、実体験を交えながら、わかりやすく解説していくから、コーヒーでも片手にリラックスして読んでいってほしい。
そもそもWALって何だっけ?
まず、WAL(Write-Ahead Logging)って覚えているかな? PostgreSQLがデータを永続化するための、超重要な仕組みだよね。
- WALの基本: データベースへの変更(INSERT, UPDATE, DELETEなど)は、まずWALバッファに書き込まれて、その後ディスク上のデータファイルに反映される。
- なぜWALが必要?: 障害発生時(停電とか、サーバーが突然落ちるとか)に、データファイルが最新の状態になっていなくても、WALログを再生することで、データの整合性を保つことができるんだ。まさに「保険」みたいなものだね。
このWALログは、一定のサイズ(デフォルトでは16MB)の「WALセグメント」という単位で作成されていく。そして、このWALセグメントがいっぱいになると、次のセグメントに切り替わる。この「いっぱいになったWALセグメント」こそが、今回のお話の主役、「WALアーカイバプロセス」が担当する対象なんだ。
WALアーカイバプロセス、その正体は?
WALアーカイバプロセス、略して「WALアーカイバ」は、PostgreSQLのバックグラウンドプロセスの一つ。その名の通り、完了したWALセグメントを「アーカイブ領域」と呼ばれる場所へコピーする、という超シンプルだけど、めちゃくちゃ大事な役割を担っているんだ。
「コピーするだけ?」って思うかもしれないけど、これがめちゃくちゃ重要なんだよ。なぜなら…
- Point-in-Time Recovery (PITR) の要: WALアーカイバがアーカイブしたWALセグメントがないと、過去のある時点(例えば、昨日の午前10時とか)にデータベースを復旧することができないんだ。フルバックアップだけじゃ、その間に発生した変更は復旧できないからね。
- WALセグメントの枯渇防止: PostgreSQLは、WALセグメントを書き換えて再利用する。もしWALアーカイバがアーカイブをサボったり、アーカイブ領域がいっぱいになったりすると、PostgreSQLは新しいWALセグメントを書き込めなくなって、最終的にはデータベースが停止してしまう、なんていう最悪の事態になりかねないんだ。
だから、このWALアーカイバプロセス、ちゃんと動いているか定期的にチェックするのは、運用者として必須のタスクなんだよ。
WALアーカイバを動かすための設定
さて、このWALアーカイバプロセス、放っておいても勝手に動いてくれるわけじゃない。ちゃんとPostgreSQLの設定ファイル `postgresql.conf` で、いくつかのパラメータを設定してあげる必要があるんだ。
1. `archive_mode`
これがWALアーカイバを有効にするかどうかのスイッチ。
- `archive_mode = off` (デフォルト): WALアーカイバは動作しない。
- `archive_mode = on`: WALアーカイバプロセスが起動し、WALセグメントのアーカイブを試みる。
- `archive_mode = always`: `on` とほぼ同じだけど、リカバリ中でもWALのアーカイブを試みる。一般的には `on` で十分なことが多いかな。
まずは、この `archive_mode` を `on` に設定しないと始まらない!
postgresql.conf
archive_mode = on
2. `archive_command`
ここが一番肝心な部分! `archive_mode = on` にしただけでは、WALセグメントをどこにコピーすればいいかPostgreSQLは知らない。この `archive_command` で、「完了したWALセグメントを、どこへ、どのようにコピーするか」を具体的にPostgreSQLに教えてあげるんだ。
`archive_command` は、シェルコマンドを指定する。PostgreSQLは、アーカイブすべきWALセグメントが見つかると、このコマンドを実行する。コマンドを実行する際には、PostgreSQLが自動的に以下の2つの変数を展開してくれるんだ。
- `%p`: アーカイブされるWALセグメントのファイルパス(例: `/var/lib/postgresql/data/pg_wal/000000010000000000000001`)
- `%f`: アーカイブされるWALセグメントのファイル名(例: `000000010000000000000001`)
例えば、WALセグメントを `/mnt/wal_archive/` というディレクトリにコピーしたい場合、こんな感じになる。
postgresql.conf
archive_command = ‘cp %p /mnt/wal_archive/%f’
【現場からのワンポイントアドバイス】
- ディレクトリの準備: コピー先のディレクトリ(例: `/mnt/wal_archive/`)は、PostgreSQLの起動ユーザー(通常は `postgres` ユーザー)が書き込めるように、事前に作成して権限を設定しておいてね。
- コマンドの成功判定: `archive_command` で指定したコマンドは、成功したら終了コード0を返し、失敗したら0以外の値を返すように実装する必要があるんだ。PostgreSQLは、コマンドが0以外の終了コードを返すと、アーカイブに失敗したと判断して、そのWALセグメントのアーカイブを何度も試みる。もしコマンドが失敗し続けて、WALセグメントが溜まっていくと、前述の「WALセグメント枯渇」の危機に直面するから、コマンドの実行結果(ログとか)はしっかり監視しよう。
- 圧縮も忘れずに!: ストレージ容量を節約するために、WALセグメントを圧縮してからアーカイブすることもよくある。例えば `gzip` を使うならこんな感じ。
# gzipで圧縮してアーカイブする場合
archive_command = ‘gzip -c %p > /mnt/wal_archive/%f.gz’
この場合、復旧時には `gunzip` などで展開する必要があるから、復旧手順もセットで考えておこうね。
- リモートストレージへのコピー: 単純なファイルコピーだけでなく、`rsync` や `scp` を使って、別のサーバーやS3のようなオブジェクトストレージにアーカイブすることも可能だ。運用環境に合わせて最適な方法を選ぼう。
実際に動いているか確認する方法
設定したら、ちゃんと動いているか確認したくなるよね。いくつか方法があるよ。
1. `pg_wal_lsn_diff()` 関数
これは、現在アクティブなWALのLSN(Log Sequence Number)と、最後にアーカイブされたWALのLSNの差分を確認できる便利な関数。
— 現在のWAL LSN
SELECT pg_current_wal_lsn();
— 最後にアーカイブされたWAL LSN
SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), pg_wal_lsn()); — pg_wal_lsn()はPostgreSQL 13以降で利用可能
— PostgreSQL 12以前の場合 (pg_last_wal_replay_lsn() や pg_last_wal_receive_lsn() と組み合わせて使う)
— archiv_cmd に %p で渡されるWALセグメントのLSNと、pg_current_wal_lsn() の差分を確認する
— 例: SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), ‘000000010000000000000002’);
この差分がどんどん大きくなっていくようだと、アーカイブが追いついていない可能性がある。
2. PostgreSQLのログを確認
`postgresql.conf` の `log_archive_commands` を `on` に設定しておくと、WALアーカイブの成功・失敗に関するログが出力されるようになる。
postgresql.conf
log_archive_commands = on
これで、`archive_command` の実行結果がログに残るから、エラーが出ていないか確認できるよ。
3. アーカイブディレクトリを確認
単純だけど、アーカイブディレクトリにWALセグメントファイルが定期的にコピーされているか確認するのも確実な方法だ。`ls -l` とかでファイルが追加されているか見てみよう。
4. `pg_stat_wal_archiver` ビュー
PostgreSQL 9.6以降では、WALアーカイバプロセスの状態を監視するためのビューが用意されている。
SELECT FROM pg_stat_wal_archiver;
このビューでは、以下の情報などが確認できる。
- `archived_count`: アーカイブされたWALセグメントの総数
- `failed_count`: アーカイブに失敗した回数
- `last_archived_time`: 最後にアーカイブされた時刻
- `last_failed_time`: 最後にアーカイブに失敗した時刻
- `current_wal_size`: 現在のWALファイルサイズ
- `size`: アーカイブされたWALの合計サイズ
`failed_count` が増えていたり、`last_archived_time` が更新されていなかったりしたら、要注意だね。
まとめ
今日は、PostgreSQLの縁の下の力持ち、「WALアーカイバプロセス」について解説してきた。
- WALアーカイバは、完了したWALセグメントをアーカイブ領域にコピーするバックグラウンドプロセス。
- `archive_mode = on` と `archive_command` の設定で制御される。
- PITR(Point-in-Time Recovery)を実現するために必須。
- WALセグメントの枯渇を防ぐためにも重要。
- アーカイブの成否は、ログや `pg_stat_wal_archiver` ビューでしっかり監視しよう。
このWALアーカイバをきちんと設定・監視しておくことで、データベースの安全性が格段に向上する。バックアップ戦略を考える上でも、まず最初にやるべきことの一つと言えるかもしれないね。
もし、これまでWALアーカイバのことをあまり意識していなかったなら、ぜひこの機会に設定を見直してみてほしい。きっと、データベース運用に対する見方が少し変わるはずだよ。
何か質問があれば、いつでも聞いてくれ! それじゃ、また次の記事で!
コメント