본문으로 건너뛰기
15.4 디스크·메모리 부족

15.4 디스크·메모리 부족

PostgreSQL이 운영을 멈추는 두 가장 흔한 사고 = 디스크 풀과 OOM Killer. 둘의 진단·즉시 대응·예방 절차를 정리합니다.

디스크 부족

어디가 찼나

df -h
# 어느 마운트 포인트가 찼는지

du -sh /var/lib/pgsql/17/data/*/   # 디렉토리별
du -sh /var/lib/pgsql/17/data/base/*/   # DB별
du -sh /var/lib/pgsql/17/data/base/<oid>/* | sort -rh | head -10   # 큰 파일

DB OID → 이름:

SELECT oid, datname FROM pg_database;

가장 큰 후보들

디렉토리의미
pg_wal/WAL — archive 실패, slot 정체
base/<oid>/사용자 데이터 — BLOAT, 큰 INSERT
base/<oid>/pg_temp_*정렬·해시 spill
log/PostgreSQL 로그 폭증
pg_tblspc/<oid>/tablespace 데이터

pg_wal/ 폭주

가장 흔한 사고입니다.

-- archive 실패?
SELECT * FROM pg_stat_archiver;

-- slot 정체?
SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag
  FROM pg_replication_slots
 ORDER BY pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) DESC NULLS LAST;

대응:

원인즉시
archive_command 실패archive 저장소 점검·해결 후 재시도 자동
slot 정체 (inactive)pg_drop_replication_slot(...)
매우 큰 트랜잭션 commit기다림 또는 abort
max_wal_size보다 큰 변경임시 키움
pg_wal/ 수동 삭제 절대 금지(14.5). 한 파일만 삭제해도 클러스터 부팅 불가능합니다. archive·slot 정리로 자동 잘림 유도.

큰 temp 파일

SELECT temp_files, pg_size_pretty(temp_bytes) FROM pg_stat_database;

원인: work_mem 부족(1.4·5.5). 한 큰 분석 쿼리가 세션 단위로 GB 만들 수 있습니다.

대응:

  • 쿼리 cancel
  • SET LOCAL work_mem = '512MB'로 디스크 spill 회피

큰 테이블·인덱스 BLOAT

-- 테이블 크기 TOP
SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total
  FROM pg_stat_user_tables
 ORDER BY pg_total_relation_size(relid) DESC
 LIMIT 10;

BLOAT 검토 → REINDEX 또는 pg_repack.

응급 — 디스크 90%+ 임박

  1. 알람: 즉시 인지
  2. 임시 공간 확보:
    • 로그 압축·삭제 (rotation 이후 파일)
    • pg_repack 진행 중인 임시 테이블
  3. 원인 해결:
    • archive 실패 해결
    • slot drop
    • autovacuum 점검
  4. 장기 대응: 디스크 증설, partition 정리

archive_command로 압축

archive 시 압축으로 저장 절약:

archive_command = 'gzip < %p > /archive/%f.gz'

또는 pgBackRest의 자체 zstd 압축.

OOM Killer

sudo dmesg | grep -iE 'killed process|out of memory'
journalctl -k | grep -iE 'oom-killer'

Killed process ... postgres가 보이면 OOM Killer 사고입니다.

원인 분석

# 최근 메모리 사용 추세
sar -r 1 10

가능한 원인:

원인진단
work_mem × 연결 × 노드 폭증application 점검
무거운 분석 쿼리가 work_mem 큼SET LOCAL 잘 안 풀음
메모리 누수 (확장 모듈)의심 모듈 disable
application 메모리도 같이 사용DB·application 분리
Linux OOM 설정 부적합14.5 참고

postmaster 보호

# systemd 유닛
Environment=PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
Environment=PG_OOM_ADJUST_VALUE=-1000

postmaster가 OOM Killer에 우선 후순위 (10.2). backend는 죽을 수 있지만 postmaster는 살아 자동 재기동.

work_mem 조정

-- 큰 work_mem 사용자 추적 — 직접 측정은 어려움
SELECT pid, usename, query
  FROM pg_stat_activity
 WHERE state = 'active' AND query ILIKE '%order by%';

대응: work_mem 작게 + 분석 사용자만 ALTER ROLE로 큰 값.

ALTER ROLE app_user SET work_mem = '8MB';
ALTER ROLE analytics SET work_mem = '256MB';

swap 관찰

free -m
# Swap used > 0이면 PostgreSQL이 swap에 빠짐 → 매우 느림

swappiness 10(13.5)로 줄입니다.

일시 정상화 절차

디스크 99% 도달

  1. autovacuum이 일을 못 하고 있는지 점검
  2. 가장 큰 inactive slot drop
  3. archive 실패 원인 해결
  4. 매우 큰 temp file 만드는 쿼리 cancel
  5. 로그 rotation·정리
  6. 그래도 안 풀리면 점검 시간으로 전환, 디스크 증설

메모리 폭주

  1. pg_stat_activity로 큰 쿼리 식별 → cancel
  2. work_mem 임시 감소
  3. application connection 줄임 (pgBouncer pool 줄임)
  4. OOM 직전이면 postmaster 보호 확인
  5. 추세 분석 후 RAM 증설 또는 최적화

예방

항목임계
디스크 80%WARN
디스크 90%CRIT — 점검 시간
pg_wal 크기max_wal_size × 2
archive 실패 알람즉시
inactive slot 알람즉시
메모리 used > 80% (swap 0 기준)WARN
OOM 1회 발생CRIT

정리

  • 디스크 풀 = 거의 항상 pg_wal/ 또는 pg_temp/ 또는 BLOAT
  • pg_wal/ 수동 삭제 금지 — archive·slot 해결로 자동 잘림
  • OOM = work_mem × connections + 분석 쿼리 큰 work_mem
  • postmaster PG_OOM_ADJUST_VALUE 보호
  • 모니터링 + 알람 + 자동화 정리가 예방의 핵심

다음 절(15.5)에서는 복제 사고 — 복제 지연·끊김을 봅니다.