Fix PostgreSQL 'FATAL: lock file postmaster.pid already exists' Sau Khi Server Crash

beginner🐘 PostgreSQL2026-06-19| Ubuntu/Debian với PostgreSQL 14 (quản lý bởi systemd), áp dụng cho PostgreSQL 12–16 trên các bản Linux tương tự

Error Message

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"?
#khởi động#lockfile#postmaster#crash#pid

Chuyện gì đã xảy ra

Server của bạn bị crash — mất điện, OOM kill, kernel panic, hoặc bất cứ lý do nào đó — và bây giờ PostgreSQL từ chối khởi động. Lỗi bạn đang thấy:

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 ghi PID của mình vào file postmaster.pid khi khởi động. Khi tắt sạch, nó sẽ xóa file đó. Còn nếu crash? Không kịp xóa. File cũ vẫn còn đó, và lần khởi động tiếp theo sẽ thấy nó rồi từ chối boot — vì nó nghĩ đã có một instance khác đang chạy rồi.

Cách fix mất chưa đến hai phút. Nhưng trước tiên, hãy xác nhận PostgreSQL thực sự không đang chạy trước khi động vào bất cứ thứ gì.

Bước 1: Xác nhận không có gì đang thực sự chạy

Trước khi xóa bất cứ thứ gì, hãy loại trừ khả năng một tiến trình PostgreSQL thực sự vẫn còn sống:

# Kiểm tra xem có tiến trình postgres nào không
ps aux | grep postgres

# Kiểm tra xem có ai đang lắng nghe trên port mặc định không
sudo ss -tlnp | grep 5432

Nếu thấy tiến trình postgres đang hoạt động hoặc có thứ gì đó đang bind vào port 5432 thì dừng lại — có thể bạn đang có hai instance xung đột nhau. Hãy kiểm tra bằng pg_lsclusters (Debian/Ubuntu) trước khi làm bất cứ điều gì khác.

Không thấy gì? File PID chắc chắn là cũ. Tiến hành tiếp.

Bước 2: Kiểm tra nội dung file PID

cat /var/run/postgresql/14-main.pid

Dòng đầu tiên là PID mà PostgreSQL đã ghi lại khi khởi động lần cuối. Kiểm tra chéo lại:

ps -p 12345

No such process — hoặc một chương trình hoàn toàn khác tình cờ kế thừa PID đó — có nghĩa là file đã cũ và có thể xóa an toàn.

Bước 3: Xóa file lock cũ

sudo rm /var/run/postgresql/14-main.pid

Còn một file lock thứ hai nằm bên trong thư mục data. Kiểm tra xem có không:

sudo ls -la /var/lib/postgresql/14/main/postmaster.pid

Thấy rồi? Xóa cái đó luôn:

sudo rm /var/lib/postgresql/14/main/postmaster.pid

/var/run/postgresql/ chứa bản sao của init system; thư mục data chứa lock nội bộ của chính PostgreSQL. Sau một lần crash, cả hai đều trở nên cũ.

Bước 4: Khởi động PostgreSQL

sudo systemctl start postgresql@14-main

# Hoặc, nếu bạn dùng tên service chung:
sudo systemctl start postgresql

Theo dõi log ngay lập tức:

sudo journalctl -u postgresql@14-main -n 50 --no-pager

Bạn cần tìm dòng database system is ready to accept connections. Thấy rồi? Xong việc.

Bước 5: Xác nhận fix thành công

# Xác nhận service đang hoạt động
sudo systemctl status postgresql@14-main

# Kết nối và chạy thử kiểm tra nhanh
sudo -u postgres psql -c "SELECT version();"

Kiểm tra xem file PID mới đã được ghi đúng chưa:

cat /var/run/postgresql/14-main.pid

Nó phải chứa PID của tiến trình vừa được khởi động. Xác nhận nó khớp với một postgres đang chạy:

ps aux | grep postgres | head -5

Nếu PostgreSQL vẫn không chịu khởi động sau khi xóa file PID

File PID cũ không phải lúc nào cũng là vấn đề duy nhất sau một lần crash. Xem log PostgreSQL để tìm manh mối:

sudo tail -100 /var/log/postgresql/postgresql-14-main.log

Các vấn đề phổ biến hay đi kèm:

  • Shared memory chưa được giải phóng — các phiên bản PostgreSQL cũ đôi khi để lại các segment shared memory. Liệt kê chúng bằng ipcs -m, sau đó xóa các entry mồ côi: ipcrm -m <shmid> (ví dụ: ipcrm -m 327681).
  • Thư mục data cần recovery — thấy database system was not properly shut down trong log là bình thường sau crash. PostgreSQL sẽ replay WAL và tự phục hồi. Cứ để nó chạy — hầu hết database hoàn tất trong chưa đầy một phút.
  • Permissions bị thay đổi — xác nhận thư mục data vẫn thuộc sở hữu của postgres: ls -la /var/lib/postgresql/14/. Sai owner? Sửa bằng sudo chown -R postgres:postgres /var/lib/postgresql/14/main.

Tham khảo nhanh: các file PID nằm ở đâu?

  • Ubuntu/Debian PG 14: /var/run/postgresql/14-main.pid
  • RHEL/CentOS/Fedora: /var/run/postgresql/postmaster.pid
  • Lock trong thư mục data: /var/lib/postgresql/14/main/postmaster.pid (hoặc nơi PGDATA của bạn trỏ tới)
  • Cài đặt tùy chỉnh: kiểm tra biến môi trường PGDATA hoặc chạy pg_lsclusters

Tại sao lỗi này cứ lặp lại (và cách giảm thiểu)

Nguyên nhân gốc rễ luôn là do tắt máy không sạch. Một vài điều đáng xem xét:

  • UPS cho database server — thường bị bỏ qua nhiều nhất ở môi trường dev và staging. Đó chính xác là nơi lỗi này hay xuất hiện.
  • TimeoutStopSec của systemd — PostgreSQL bị kill giữa chừng khi reboot vì mất quá nhiều thời gian để flush? Hãy tăng timeout dừng lên. Thêm TimeoutStopSec=120 vào service unit bằng sudo systemctl edit postgresql@14-main.
  • OOM killer — nếu Postgres bị OOM kill, đó là vấn đề hoàn toàn khác. Chạy dmesg | grep -i oom sau khi crash để xác nhận.
  • VM snapshot — revert một VM đang chạy về snapshot sẽ để lại file PID cũ mỗi lần. Hãy tắt máy sạch trước khi snapshot, hoặc chấp nhận phải chạy qua cách fix này sau mỗi lần revert.

Cách fix này ít rủi ro. Cơ chế crash recovery dựa trên WAL của PostgreSQL tự xử lý tính toàn vẹn dữ liệu. Xóa file PID chỉ đơn giản là dọn sạch một artifact sổ sách mà vụ crash để lại.

Related Error Notes