🐘

ループバック・デバイスを使ってディスク関連エラー時のPostgreSQLの挙動を確かめる

2024/12/04に公開

はじめに

PostgreSQLのデータ保存先を設計する際には、耐障害性や性能の観点からOS領域とは別のディスクにデータベースデータを保存するようにすることが多いと思います。
この記事では、PostgreSQLのデータを別ディスクに置いたときの挙動を簡単に確認する方法を解説します。実際の挙動と異なる可能性があるので、その点は十分ご注意ください。

実験内容

ループバック・デバイス使ってWAL領域を別ディスクに保存することを模擬して、ディスクをアンマウントしたとき、ディスクフルになったとき、の挙動を確かめます。

環境

  • PostgreSQL 17.2
  • Rocky Linux 8.9

実施手順

ループバック・デバイスをマウントする

// ファイルの作成
$ dd if=/dev/zero of=/tmp/test.img bs=1M count=100
$ ls -l /tmp/test.img
-rw-rw-r-- 1 shinya shinya 104857600 Dec  4 18:15 /tmp/test.img

// ファイルシステムの作成
$ mkfs.xfs /tmp/test.img

// ループバック・デバイスとしてマウント
$ sudo mkdir /mnt/pgwal
$ sudo mount -o loop /tmp/test.img /mnt/pgwal

// マウントの確認
$ df -h /mnt/pgwal
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       95M  6.0M   89M   7% /mnt/pgwal

データベースクラスタを作成する

// ループバック・デバイスをマウントしたディレクトリをWAL領域に指定
$ sudo chown -R shinya:shinya /mnt/pgwal
$ initdb --encoding=UTF8 --no-locale --waldir=/mnt/pgwal

// PostgreSQLを起動
$ pg_ctl start

// /mnt/pgwalにWALファイルが作成されたことを確認
$ ls -l /mnt/pgwal
total 16384
-rw------- 1 shinya shinya 16777216 Dec  4 18:23 000000010000000000000001
drwx------ 2 shinya shinya        6 Dec  4 18:23 archive_status
drwx------ 2 shinya shinya        6 Dec  4 18:23 summaries

pgbench実行中にアンマウントしてみる

Terminal 1
$ pgbench -i -s 1
$ pgbench -T 300 -s 1
Terminal 2
// オプションを付けずにアンマウントしようしてもbusyでできない
$ sudo umount /mnt/pgwal
umount: /mnt/pgwal: target is busy.

// /mnt/pgwal内のファイルを掴んでいるプロセスを確認
// walwriterプロセスとbackendプロセスがWALファイルを掴んでいる
$ lsof /mnt/pgwal/*
postgres 880450 shinya    6u   REG    7,0 16777216  132 /mnt/pgwal/000000010000000000000002
postgres 880819 shinya   29u   REG    7,0 16777216  132 /mnt/pgwal/000000010000000000000002
$ ps u -p 880450 -p 880819
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
shinya    880450  0.0  0.0 180424  8340 ?        Ss   18:30   0:00 postgres: walwriter 
shinya    880819 50.0  0.1 182644 38104 ?        Ds   18:31   0:27 postgres: shinya postgres [local] COMMIT

// lazyアンマウントするとPostgreSQLがクラッシュ
$ sudo umount -l /mnt/pgwal
ログ
2024-12-04 18:33:13.517 JST [882475] PANIC:  could not create file "pg_wal/xlogtemp.882475": Permission denied
2024-12-04 18:33:13.524 JST [880446] LOG:  server process (PID 882475) was terminated by signal 6: Aborted
2024-12-04 18:33:13.524 JST [880446] DETAIL:  Failed process was running: autovacuum: ANALYZE public.pgbench_accounts
2024-12-04 18:33:13.524 JST [880446] LOG:  terminating any other active server processes
2024-12-04 18:33:13.572 JST [880446] LOG:  all server processes terminated; reinitializing
2024-12-04 18:33:13.580 JST [882516] LOG:  database system was interrupted; last known up at 2024-12-04 18:30:43 JST
2024-12-04 18:33:13.580 JST [882516] LOG:  creating missing WAL directory "pg_wal/archive_status"
2024-12-04 18:33:13.580 JST [882516] FATAL:  could not create missing directory "pg_wal/archive_status": Permission denied
2024-12-04 18:33:13.580 JST [880446] LOG:  startup process (PID 882516) exited with exit code 1
2024-12-04 18:33:13.580 JST [880446] LOG:  aborting startup due to startup process failure
2024-12-04 18:33:13.581 JST [880446] LOG:  database system is shut down

ディスクフルにしてみる

// 再度マウント
$ sudo mount -o loop /tmp/test.img /mnt/pgwal

// 大きめのデータを作成するとPostgreSQLがクラッシュ
$ pgbench -i -s 100
ログ
2024-12-04 18:40:05.973 JST [886944] PANIC:  could not write to file "pg_wal/xlogtemp.886944": No space left on device
2024-12-04 18:40:05.973 JST [886944] CONTEXT:  COPY pgbench_accounts, line 768000
2024-12-04 18:40:05.973 JST [886944] STATEMENT:  copy pgbench_accounts from stdin with (freeze on)
2024-12-04 18:40:05.980 JST [886751] LOG:  server process (PID 886944) was terminated by signal 6: Aborted
2024-12-04 18:40:05.980 JST [886751] DETAIL:  Failed process was running: copy pgbench_accounts from stdin with (freeze on)
2024-12-04 18:40:05.980 JST [886751] LOG:  terminating any other active server processes
2024-12-04 18:40:05.981 JST [886751] LOG:  all server processes terminated; reinitializing
2024-12-04 18:40:05.987 JST [886961] LOG:  database system was interrupted; last known up at 2024-12-04 18:39:55 JST
2024-12-04 18:40:06.318 JST [886961] LOG:  database system was not properly shut down; automatic recovery in progress
2024-12-04 18:40:06.320 JST [886961] LOG:  redo starts at 0/147FB28
2024-12-04 18:40:06.447 JST [886961] LOG:  redo done at 0/5FFE1F0 system usage: CPU: user: 0.08 s, system: 0.03 s, elapsed: 0.12 s
2024-12-04 18:40:06.453 JST [886961] FATAL:  could not write to file "pg_wal/xlogtemp.886961": No space left on device
2024-12-04 18:40:06.454 JST [886751] LOG:  startup process (PID 886961) exited with exit code 1
2024-12-04 18:40:06.454 JST [886751] LOG:  terminating any other active server processes
2024-12-04 18:40:06.455 JST [886751] LOG:  shutting down due to startup process failure
2024-12-04 18:40:06.458 JST [886751] LOG:  database system is shut down

まとめ

ループバック・デバイスを使ってディスク関連エラー時のPostgreSQLの挙動を確かめました。エラーになるのはわかっているけど、どんなエラーメッセージだったかな、というときなど手軽に試せるのでおすすめです。
冒頭にも述べましたが、実際のディスクの挙動と異なる可能性があるので、その点にはくれぐれもご注意をお願いします。

Discussion