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%+ 임박
- 알람: 즉시 인지
- 임시 공간 확보:
- 로그 압축·삭제 (rotation 이후 파일)
pg_repack진행 중인 임시 테이블
- 원인 해결:
- archive 실패 해결
- slot drop
- autovacuum 점검
- 장기 대응: 디스크 증설, 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=-1000postmaster가 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% 도달
- autovacuum이 일을 못 하고 있는지 점검
- 가장 큰 inactive slot drop
- archive 실패 원인 해결
- 매우 큰 temp file 만드는 쿼리 cancel
- 로그 rotation·정리
- 그래도 안 풀리면 점검 시간으로 전환, 디스크 증설
메모리 폭주
pg_stat_activity로 큰 쿼리 식별 → cancel- work_mem 임시 감소
- application connection 줄임 (pgBouncer pool 줄임)
- OOM 직전이면 postmaster 보호 확인
- 추세 분석 후 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)에서는 복제 사고 — 복제 지연·끊김을 봅니다.