DockerでPostgreSQLを運用しているのだが、メンテナンスのためにDBを停止しようとして、誤ってCtrl-C
を連打してしまい強制終了してしまった。
慌てて再起動を試みるも、次のようなエラーで起動しなくなっていた。
2021-08-27 16:16:22.532 UTC [1] LOG: starting PostgreSQL 13.4 (Debian 13.4-1.pgdg100+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
2021-08-27 16:16:22.532 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2021-08-27 16:16:22.532 UTC [1] LOG: listening on IPv6 address "::", port 5432
2021-08-27 16:16:22.536 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-08-27 16:16:22.542 UTC [27] LOG: database system was shut down at 2021-08-27 16:13:35 UTC
2021-08-27 16:16:22.543 UTC [27] LOG: invalid primary checkpoint record
2021-08-27 16:16:22.543 UTC [27] PANIC: could not locate a valid checkpoint record
2021-08-27 16:16:22.710 UTC [1] LOG: startup process (PID 27) was terminated by signal 6: Aborted
2021-08-27 16:16:22.710 UTC [1] LOG: aborting startup due to startup process failure
2021-08-27 16:16:22.712 UTC [1] LOG: database system is shut down
ポイントは7行目の
PANIC: could not locate a valid checkpoint record
で、Stack Overflow1によるとWAL(トランザクションログ)が壊れているらしい。
データのバックアップを取った後に、以下のコマンドでWALをリセットして復旧を試みる(PostgreSQL 9まではpg_resetxlog
というコマンドだったらしい)。
pg_resetwal /var/lib/postgresql/data
Docker Composeで停止中のコンテナに対して実行する場合は以下の通り。
DB_USER_NAME
は、PostgreSQLの起動時に環境変数POSTGRES_USER
で指定したユーザー名(デフォルトはpostgres
)。
COMPOSE_SERVICE_NAME
は、docker-compose.yml
で指定したデータベースコンテナのサービス名。
docker compose run --user=DB_USER_NAME COMPOSE_SERVICE_NAME pg_resetwal /var/lib/postgresql/data
コマンドの実行後はデータ破損がないか確認し、必要に応じて修正を行うこと。私の環境では現在のところ正常に稼働している。