본문으로 건너뛰기
15.1 일반적인 에러 패턴

15.1 일반적인 에러 패턴

PostgreSQL 운영에서 자주 보는 에러를 패턴별로 정리합니다. 메시지·원인·즉시 대응·예방 절차를 함께.

1. FATAL: too many connections

FATAL:  remaining connection slots are reserved for non-replication superuser connections

| 원인 | max_connections 초과 |

즉시 대응:

-- 가장 idle한 backend 종료
SELECT pg_terminate_backend(pid)
  FROM pg_stat_activity
 WHERE state = 'idle'
   AND now() - state_change > interval '10 min';

예방:

  • pgBouncer 도입 (13.4)
  • application connection leak 점검
  • max_connections은 OS·메모리 한계까지만

2. ERROR: could not extend file ...: No space left on device

| 원인 | 디스크 풀 |

즉시 대응:

df -h
# 어떤 디렉토리가 찼나
du -sh /var/lib/pgsql/17/data/{base,pg_wal,log,base/pg_temp}

흔한 후보:

  • pg_wal/ — archive 실패 또는 slot 정체
  • base/pg_temp — 큰 정렬 temp file
  • log/ — 로그 폭증

예방: 디스크 80% 알람, slot 모니터링, log rotation.

3. FATAL: the database system is starting up

FATAL:  the database system is starting up

| 원인 | crash recovery 또는 starting |

대응: 기다림. pg_stat_activity로 진행률입니다.

SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn();

WAL 재생 길어지면 restartpoint 체크포인트 빈도 확인합니다. 매우 길면 recovery_target 점검합니다.

4. WARNING: archive_command failed

LOG:  archive command failed with exit code 1
DETAIL:  The failed archive command was: ...

| 원인 | archive 저장소 접근 실패 (네트워크·권한·full) |

즉시 대응: 외부 저장소 확인, archive_command 수동 실행합니다.

sudo -u postgres pgbackrest --stanza=main archive-push /tmp/test.wal

pg_wal/ 가득 차기 전에 해결 필수입니다.

예방: pg_stat_archiver.last_failed_time 알람을 받습니다.

5. ERROR: deadlock detected

ERROR:  deadlock detected
DETAIL:  Process 1234 waits for ShareLock on transaction 5678; blocked by process ...

| 원인 | 두 트랜잭션이 서로의 락 대기 |

대응: application 재시도 + 락 순서 일관성(14.4).

-- 데드락 통계 추적
SELECT datname, deadlocks FROM pg_stat_database;

6. canceling statement due to conflict with recovery

| 원인 | hot standby에서 vacuum cleanup 충돌 (12.3) |

대응: application 재시도. 자주 발생하면 max_standby_streaming_delay 또는 hot_standby_feedback.

7. WARNING: there is no transaction in progress

WARNING:  there is no transaction in progress

| 원인 | COMMIT 또는 ROLLBACK을 트랜잭션 없이 |

대응: application 로직 점검합니다. autocommit 모드 확인합니다.

8. ERROR: current transaction is aborted, commands ignored until end of transaction block

ERROR:  current transaction is aborted

| 원인 | 이전 SQL이 error → 트랜잭션 abort 상태, 추가 SQL은 모두 무시. ROLLBACK 또는 COMMIT 필요 |

대응:

try:
    cur.execute("BAD SQL")
except:
    conn.rollback()   # 명시

ORM은 자동 ROLLBACK이 일반적이지만 raw connection은 아님.

9. OperationalError: server closed the connection unexpectedly

| 원인 | 서버 측 backend가 종료 — crash, OOM, idle timeout, pg_terminate_backend |

대응:

  • PostgreSQL 로그에서 종료 원인 확인
  • OOM이면 dmesg | grep -i oom
  • application은 connection retry

10. ERROR: out of shared memory

ERROR:  out of shared memory
HINT:  You might need to increase max_locks_per_transaction.

| 원인 | 락·prepared statement 등 shared 영역의 슬롯 부족 — 흔히 많은 파티션 + 한 트랜잭션이 모든 파티션 락 |

대응:

max_locks_per_transaction = 256     # restart 필요
max_pred_locks_per_transaction = 256

11. ERROR: cannot execute UPDATE in a read-only transaction

| 원인 | hot standby 또는 default_transaction_read_only = on |

대응: 쓰기는 primary로 라우팅. HAProxy·풀러 설정 확인합니다.

12. ERROR: relation "..." does not exist

| 원인 | 테이블 없음 · 잘못된 search_path · 다른 스키마 |

대응:

SHOW search_path;
SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'orders';

13. ERROR: permission denied for table ...

| 원인 | GRANT 없음 |

대응:

-- 권한 확인
SELECT grantee, privilege_type
  FROM information_schema.table_privileges
 WHERE table_name = 'orders';

pg_monitor·pg_read_all_data 같은 미리 정의 역할 활용합니다.

14. ERROR: invalid input syntax for integer: "..."

| 원인 | application이 잘못된 타입 전달 — 또는 SQL injection 시도 |

대응: parameterized query 사용합니다.

15. ERROR: missing chunk number ... for toast value ...

| 원인 | TOAST corruption — 매우 심각 |

대응:

-- 영향 받는 row 식별
SELECT id FROM big_table WHERE big_col IS NOT NULL ORDER BY id;
-- 오류 발생하는 직전 id를 추적

-- 영향 row 제외하고 다른 곳으로 export
SELECT * FROM big_table WHERE ctid::text NOT LIKE '(<bad>,%)';

복구 한계 — 백업에서 PITR 검토합니다.

16. database is being recovered

| 원인 | startup process가 WAL 재생 중 |

대응: 기다림. pg_last_wal_replay_lsn으로 진행률입니다.

17. pg_hba.conf rejects connection for ...

FATAL:  pg_hba.conf rejects connection for host "203.0.113.5", user "alice", database "app", no encryption

| 원인 | 명시적 reject 또는 매칭 행 없음 (9.2) |

대응: pg_hba.conf 점검합니다.

SELECT * FROM pg_hba_file_rules;

18. WAL contains references to invalid pages

PANIC 또는 ERROR. 페이지 손상 가능성이 있습니다.

대응:

  • data_checksums 켜져 있으면 자세한 정보
  • pg_basebackup으로 새로 복원
  • 데이터 손상 — 백업·전문가 자문

19. lock not available

ERROR:  could not obtain lock on relation "..."

| 원인 | lock_timeout 만료 또는 NOWAIT |

대응: 락 잡고 있는 세션 식별 후 결정합니다.

20. application 로그에 EOF detected / Connection reset by peer

| 원인 | network 또는 PostgreSQL 측 종료 |

대응:

  • application retry
  • PostgreSQL 로그에서 server 측 사유 확인
  • TCP keepalive 설정

진단 워크플로

    flowchart TD
  ERR["에러 발생"]
  LOG["PostgreSQL log 확인"]
  CTX{"context"}
  APP["application 측 진단<br/>(타입·SQL·로직)"]
  CON["연결 측 진단<br/>(pg_hba, network)"]
  DB["DB 측 진단<br/>(pg_stat_activity, pg_locks)"]
  OS["OS 측 진단<br/>(메모리·디스크·dmesg)"]

  ERR --> LOG --> CTX
  CTX -- "application 메시지" --> APP
  CTX -- "FATAL on connect" --> CON
  CTX -- "ERROR in query" --> DB
  CTX -- "PANIC·OOM" --> OS

  classDef step fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
  class ERR,LOG,APP,CON,DB,OS step
  

정리

  • 모든 사고의 첫 단계 = PostgreSQL 로그
  • pg_stat_activity·pg_locks로 실시간 진단
  • 디스크 풀·OOM은 OS 도구로 확인
  • 자주 보는 에러 20종은 원인 매핑 표로 외움 — 신속 대응

다음 절(15.2)에서는 느린 쿼리 진단의 표준 — 슬로우 쿼리 진단 워크플로우를 봅니다.