何が起きたのか
サーバーがクラッシュしました — 停電、OOMキル、カーネルパニック、原因は何であれ — 今やPostgreSQLが起動を拒否しています。表示されているエラーは次のとおりです:
FATAL: lock file "/var/run/postgresql/14-main.pid" already exists
HINT: Is another postmaster (PID 12345) running in data directory "/var/lib/postgresql/14/main"?
PostgreSQLは起動時にPIDをpostmaster.pidへ書き込みます。正常シャットダウン時にはそのファイルを削除します。クラッシュした場合は?削除の機会がありません。古いファイルが残り続け、次回の起動時にそれを検出して、別のインスタンスがすでに実行中だと判断して起動を拒否します。
修正には2分もかかりません。ただし最初に、何かを触る前にPostgreSQLが実際に動いていないことを確認してください。
ステップ1:実際に何も動いていないことを確認する
何かを削除する前に、PostgreSQLプロセスが本当に生きている可能性を排除します:
# postgresプロセスが存在するか確認
ps aux | grep postgres
# デフォルトポートでリッスンしているものがあるか確認
sudo ss -tlnp | grep 5432
アクティブなpostgresプロセスやポート5432にバインドされているものがある場合は作業を止めてください — 2つのインスタンスが衝突している可能性があります。他の作業を行う前にpg_lsclusters(Debian/Ubuntu)で調査してください。
何も表示されませんか?PIDファイルは確実に古くなっています。続行してください。
ステップ2:PIDファイルの内容を確認する
cat /var/run/postgresql/14-main.pid
最初の行は、PostgreSQLが最後に起動したときに記録したPIDです。これをクロスチェックします:
ps -p 12345
No such process — またはそのPIDをたまたま引き継いだまったく無関係なプログラム — が表示された場合、ファイルは古くなっており安全に削除できます。
ステップ3:古いロックファイルを削除する
sudo rm /var/run/postgresql/14-main.pid
データディレクトリ自体の中にも2つ目のロックファイルがあります。確認してください:
sudo ls -la /var/lib/postgresql/14/main/postmaster.pid
見つかりましたか?こちらも削除します:
sudo rm /var/lib/postgresql/14/main/postmaster.pid
/var/run/postgresql/はinitシステムのコピーを保持し、データディレクトリはPostgreSQL自身の内部ロックを保持します。クラッシュ後は、両方が古くなります。
ステップ4:PostgreSQLを起動する
sudo systemctl start postgresql@14-main
# または、汎用サービス名を使用している場合:
sudo systemctl start postgresql
すぐにログを確認します:
sudo journalctl -u postgresql@14-main -n 50 --no-pager
database system is ready to accept connectionsが表示されるのを確認してください。表示されましたか?完了です。
ステップ5:修正を確認する
# サービスがアクティブであることを確認
sudo systemctl status postgresql@14-main
# 接続して簡単な動作確認を実行
sudo -u postgres psql -c "SELECT version();"
新しいPIDファイルが正しく書き込まれたことを確認します:
cat /var/run/postgresql/14-main.pid
新しく起動したプロセスのPIDが含まれているはずです。実行中のpostgresと一致することを確認します:
ps aux | grep postgres | head -5
PIDファイルを削除してもPostgreSQLが起動しない場合
古いPIDファイルがクラッシュの唯一の被害というわけではありません。手がかりを得るためにPostgreSQLのログを確認してください:
sudo tail -100 /var/log/postgresql/postgresql-14-main.log
よくある二次的な問題:
- 共有メモリが解放されていない — 古いバージョンのPostgreSQLは共有メモリセグメントを残すことがありました。
ipcs -mでリストアップし、孤立したエントリを削除します:ipcrm -m <shmid>(例:ipcrm -m 327681)。 - データディレクトリの回復が必要 — ログに
database system was not properly shut downが表示されるのはクラッシュ後では正常です。PostgreSQLはWALをリプレイして自動的に回復します。そのまま実行させてください — ほとんどのデータベースは1分以内に完了します。 - パーミッションが変更された — データディレクトリがまだ
postgresによって所有されているか確認します:ls -la /var/lib/postgresql/14/。所有者が間違っていますか?sudo chown -R postgres:postgres /var/lib/postgresql/14/mainで修正してください。
クイックリファレンス:PIDファイルの場所
- Ubuntu/Debian PG 14:
/var/run/postgresql/14-main.pid - RHEL/CentOS/Fedora:
/var/run/postgresql/postmaster.pid - データディレクトリのロック:
/var/lib/postgresql/14/main/postmaster.pid(またはPGDATAが指す場所) - カスタムインストール:
PGDATA環境変数を確認するか、pg_lsclustersを実行してください
なぜこれが繰り返されるのか(そして発生を減らす方法)
根本原因は常に不正なシャットダウンです。対処する価値のあることがいくつかあります:
- データベースサーバー用のUPS — 開発環境やステージング環境で最もよく省略されます。このエラーが発生するのはまさにそのような場所です。
- systemdの
TimeoutStopSec— フラッシュに時間がかかりすぎてPostgreSQLが再起動中にキルされていますか?停止タイムアウトを増やしてください。sudo systemctl edit postgresql@14-mainでサービスユニットにTimeoutStopSec=120を追加します。 - OOMキラー — PostgreSQLがOOMキルされている場合、それはまったく別の問題です。クラッシュ後に
dmesg | grep -i oomを実行して確認してください。 - VMスナップショット — 実行中のVMをスナップショットに戻すと、毎回古いPIDファイルが残ります。スナップショットを取る前にクリーンにシャットダウンするか、各リバート後にこの修正手順を実行することを覚悟してください。
この修正はリスクが低いです。PostgreSQLのWALベースのクラッシュリカバリが独自にデータの整合性を処理します。PIDファイルを削除するのは、クラッシュが残した管理上の痕跡を消去するだけです。

