2026년 09월 25일 | DBMS Error 가이드
이 글에서 다루는 내용
F0001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
F0001 lock file exists 는?
PostgreSQL 에러 코드 F0001 lock file exists는 PostgreSQL 서버가 시작될 때 이미 데이터 디렉터리에 잠금 파일(postmaster.pid)이 존재할 경우 발생하는 오류입니다. 이 잠금 파일은 PostgreSQL 인스턴스가 정상적으로 실행 중임을 나타내는 파일로, 서버가 비정상 종료되거나 충돌(crash)했을 때 자동으로 삭제되지 않고 남아 있을 수 있습니다. 그 결과, 새로운 PostgreSQL 프로세스가 시작을 시도할 때 기존 잠금 파일을 발견하고 충돌을 방지하기 위해 시작을 거부하게 됩니다.
주요 발생 원인
1. 서버 비정상 종료(Crash) 후 잔류 PID 파일
가장 흔한 원인은 PostgreSQL 서버가 SIGKILL 시그널, 시스템 전원 차단, 혹은 OOM Killer에 의해 강제 종료된 후 postmaster.pid 파일이 데이터 디렉터리에 그대로 남아 있는 경우입니다. 정상적인 pg_ctl stop 명령이나 service postgresql stop은 종료 시 이 파일을 자동으로 삭제하지만, 강제 종료 시에는 이 과정이 생략됩니다. 이로 인해 PostgreSQL은 다음 시작 시 여전히 인스턴스가 실행 중이라고 오판하여 시작을 거부합니다.
2. 동일 데이터 디렉터리를 가리키는 중복 인스턴스 실행 시도
하나의 PostgreSQL 데이터 디렉터리($PGDATA)에 두 개 이상의 PostgreSQL 프로세스가 접근하려 할 때 이 에러가 발생할 수 있습니다. 예를 들어, 시스템 부팅 스크립트와 수동 실행 명령이 동시에 실행되거나, Docker 컨테이너가 재시작되면서 이전 인스턴스의 잠금 파일이 볼륨에 남아 있는 경우입니다. 이 상황은 특히 컨테이너 환경이나 VM 스냅샷 복원 시 자주 관찰됩니다.
3. NFS 또는 공유 스토리지 마운트 문제
PostgreSQL 데이터 디렉터리가 NFS나 SAN 같은 공유 스토리지에 위치할 경우, 네트워크 장애나 마운트 해제 후 재마운트 과정에서 잠금 파일이 비정상적으로 잔류할 수 있습니다. 공유 스토리지 환경에서는 파일 시스템 레벨의 잠금 메커니즘이 불안정하게 동작하는 경우가 있어, postmaster.pid 파일이 삭제되지 않고 스토리지에 남아 있을 수 있습니다. 이 경우 단순히 파일을 삭제하기 전에 실제로 실행 중인 PostgreSQL 프로세스가 없는지 반드시 확인해야 합니다.
해결 방법
1단계: 실제로 PostgreSQL 프로세스가 실행 중인지 확인
무조건 파일을 삭제하기 전에, 실제로 살아있는 PostgreSQL 프로세스가 있는지 반드시 확인해야 합니다.
-- postmaster.pid 파일 내용 확인 (첫 번째 줄이 PID)
-- 터미널에서 실행:
-- cat $PGDATA/postmaster.pid
-- 해당 PID가 실제로 실행 중인지 확인
-- ps -ef | grep <PID>
-- PostgreSQL 프로세스 전체 확인
-- ps aux | grep postgres
운영 시스템에서는 아래 SQL로 현재 연결 상태를 확인하는 것도 좋은 방법입니다.
-- 만약 DB에 접속이 가능한 상태라면 현재 연결 확인
SELECT pid, usename, application_name, client_addr, state, query_start
FROM pg_stat_activity
WHERE datname = current_database()
ORDER BY query_start DESC;
2단계: 프로세스가 없음을 확인 후 잠금 파일 제거
PostgreSQL 프로세스가 완전히 없음을 확인한 후에만 아래 절차를 진행하세요.
-- 터미널(bash)에서 실행:
-- 잠금 파일 위치 확인
-- echo $PGDATA
-- ls -la $PGDATA/postmaster.pid
-- 잠금 파일 삭제 (프로세스 없음이 100% 확인된 후에만 실행!)
-- rm -f $PGDATA/postmaster.pid
-- PostgreSQL 재시작
-- pg_ctl start -D $PGDATA
-- 또는
-- systemctl start postgresql
3단계: 강제 종료 후 데이터 무결성 확인
비정상 종료 후에는 데이터 무결성을 점검하는 것이 필수입니다.
-- PostgreSQL 재시작 후 데이터베이스 상태 확인
SELECT datname, pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
ORDER BY pg_database_size(datname) DESC;
-- 트랜잭션 로그(WAL) 무결성 확인
-- pg_waldump를 활용하거나 아래로 체크포인트 강제 실행
CHECKPOINT;
-- 테이블 손상 여부 확인 (pg_amcheck 또는 VACUUM)
VACUUM VERBOSE ANALYZE;
-- 특정 테이블 손상 여부 직접 확인
SELECT schemaname, tablename, attname, n_distinct, correlation
FROM pg_stats
WHERE tablename = 'your_table_name';
4단계: Docker/컨테이너 환경에서의 처리
-- Docker 환경에서 컨테이너 재시작 전 볼륨 내 pid 파일 확인
-- docker exec -it <container_name> ls /var/lib/postgresql/data/postmaster.pid
-- 컨테이너 내부에서 직접 파일 삭제 후 재시작
-- docker exec -it <container_name> rm -f /var/lib/postgresql/data/postmaster.pid
-- docker restart <container_name>
-- docker-compose 환경
-- docker-compose down && docker-compose up -d
예방 방법
1. 안전한 종료 절차 및 모니터링 스크립트 운영
PostgreSQL 서버를 종료할 때는 반드시 pg_ctl stop -m fast 또는 systemctl stop postgresql을 사용하고, 강제 종료(kill -9)는 절대적으로 피해야 합니다. 다음과 같은 종료 전 체크 스크립트를 운영 프로세스에 포함시키는 것을 강력히 권장합니다.
-- 종료 전 활성 연결 및 장기 트랜잭션 확인
SELECT pid, usename, now() - pg_stat_activity.query_start AS duration, query, state
FROM pg_stat_activity
WHERE state != 'idle'
AND now() - pg_stat_activity.query_start > INTERVAL '5 minutes'
ORDER BY duration DESC;
-- 장기 잠금 확인
SELECT pid, relation::regclass, mode, granted
FROM pg_locks
WHERE NOT granted;
시스템 레벨에서는 systemd의 TimeoutStopSec을 충분히 크게 설정하여 PostgreSQL이 정상 종료할 시간을 확보해야 합니다.
2. 자동화된 상태 점검 및 알림 체계 구축
postmaster.pid 파일과 실제 프로세스 상태를 주기적으로 비교하는 헬스체크 스크립트를 크론(cron)이나 모니터링 시스템(Prometheus, Zabbix 등)에 등록하여 불일치가 발생할 경우 즉시 알림을 받도록 구성하세요.
-- PostgreSQL 재시작 후 pg_stat_bgwriter로 비정상 종료 이력 확인
SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time,
buffers_clean, maxwritten_clean, buffers_backend_fsync,
stats_reset
FROM pg_stat_bgwriter;
-- 비정상 종료 횟수가 많다면 shared_buffers, work_mem 튜닝 검토
-- postgresql.conf에서 아래 설정 확인
-- shared_buffers = 256MB (전체 RAM의 25%)
-- checkpoint_completion_target = 0.9
-- max_wal_size = 1GB
관련 에러
- 57P03 (
cannot_connect_now): 서버가 시작 중이거나 복구 중일 때 연결 시도 시 발생하며, F0001과 함께 서버 시작 실패 상황에서 연계되어 나타날 수 있습니다. - 58000 (
system_error): 운영 체제 레벨의 파일 시스템 오류로 인해 PID 파일 접근이 실패할 때 발생할 수 있습니다. - XX000 (
internal_error): 비정상 종료 후 데이터 파일 손상이 함께 발생한 경우 재시작 과정에서 나타날 수 있으며, F0001 해결 후에도 이 에러가 발생하면 WAL 복구나 백업 복원을 고려해야 합니다. - 53300 (
too_many_connections): 잠금 파일 문제 해결 후 재시작 시 기존에 쌓여 있던 연결 요청이 몰릴 경우 발생할 수 있어max_connections설정을 함께 점검하는 것이 좋습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.