이번에 다룰 주제는 PostgreSQL에서 'Idle Session의 Memory 사용' 이다.
궁금하다. PostgreSQL에서 Idle Connection이 메모리를 차지할까?
시간을 아끼기 위해 결론부터 말하면,
PostgreSQL에서는 Idle Session(유휴 세션)이 일정량의 메모리를 유지하면서도 시스템 리소스를 점유한다.
work_mem, temp_buffers, shared_buffers 등의 메모리 설정이 높은 경우, Idle Session이 많으면 메모리 낭비가 발생한다.
1. PostgreSQL의 Idle Session이 차지하는 메모리
PostgreSQL에서 클라이언트가 연결되면 각 세션(백엔드 프로세스)이 고유한 메모리를 할당받습니다.
✅ Idle Session의 주요 메모리 점유 영역
- Per-Connection Memory (개별 연결별 메모리)
- work_mem: 한 쿼리당 할당되는 작업 메모리
- temp_buffers: 개별 연결이 사용하는 임시 버퍼
- maintenance_work_mem: VACUUM, CREATE INDEX 등의 유지보수 작업 시 사용됨
- Shared Memory (PostgreSQL 전체 공유)
- shared_buffers: PostgreSQL 전체에서 사용하는 캐시 영역
- wal_buffers: WAL(Write-Ahead Logging) 관련 데이터 캐시
💡 Idle 상태에서도 기본적인 개별 연결 메모리는 유지되므로, Idle Connection이 많으면 메모리 낭비 발생!
2. Idle Session의 유형
PostgreSQL에서 pg_stat_activity.state를 확인하면 Idle 상태의 세션을 분석할 수 있다.
(1) idle
- 트랜잭션이 열려 있지 않은 단순 유휴 세션
- 단순히 연결만 유지하면서 사용자 입력을 기다리는 상태
- 일반적으로 심각한 문제는 없지만 오래 유지되면 불필요한 메모리 소비 발생
(2) idle in transaction
- 트랜잭션이 열려 있지만 아무 작업도 수행하지 않는 상태
- 예: BEGIN; 실행 후, COMMIT 또는 ROLLBACK 없이 대기 중
- 문제: 이 상태가 오래 지속되면 lock을 유지하면서 다른 트랜잭션을 블로킹할 수 있음
(3) idle in transaction (aborted)
- 트랜잭션이 비정상적으로 중단(aborted) 되었으나 연결은 유지됨
- ROLLBACK을 실행해야 하지만, 클라이언트가 응답하지 않으면 트랜잭션이 종료되지 않음
- 문제: 메모리뿐만 아니라 다른 트랜잭션도 블로킹 가능.
🔹 Idle Session 확인 Query
SELECT pid, usename, state, query, age(clock_timestamp(), query_start) AS idle_time
FROM pg_stat_activity
WHERE state LIKE 'idle%'
ORDER BY idle_time DESC;
3. Idle Session이 많으면 어떤 문제가 발생할까?
Idle Session이 많아지면 다음과 같은 문제가 발생할 수 있다.
| 메모리 낭비 | 각 Idle Session이 work_mem, temp_buffers 등의 메모리를 점유 |
| 커넥션 제한 도달 | max_connections를 초과하면 새로운 연결 불가 |
| Lock 유지 | idle in transaction 상태에서는 다른 트랜잭션이 대기할 수 있음 |
| VACUUM 지연 | 트랜잭션이 열려 있으면 VACUUM이 진행되지 않음 |
| 성능 저하 | 불필요한 연결이 많으면 PostgreSQL 프로세스 관리 부담 증가 |
4. Idle Session이 많을 때 해결 방법
(1) 오래된 Idle Session 강제 종료
오래된 Idle Connection을 자동으로 종료는 idle_in_transaction_session_timeout 설정으로.
-- 특정 시간이 지나면 자동으로 세션 종료
ALTER SYSTEM SET idle_in_transaction_session_timeout = '5min';
-- 5분 이상 idle in transaction 상태가 지속되면 자동 종료
-- 현재 오래된 Idle 세션을 즉시 종료
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction' AND now() - query_start > interval '10 minutes';
-- 10분 이상 유휴 상태의 트랜잭션을 종료
(2) pg_bouncer를 이용한 Connection Pooling
Idle Session이 많으면 Connection Pooling을 활용하는 것이 효과적일 수 있다.
PgBouncer를 사용하면 짧은 연결을 효율적으로 관리하여 메모리 사용량을 줄일 수 있음.
(3) max_connections 조정 및 커넥션 제한
Idle Session이 많아지면 PostgreSQL이 커넥션을 너무 많이 허용하지 않도록 조정하는 것이 중요하다.
-- max_connections 줄이기
max_connections = 200 -- 예를들어 기본값 1000 → 200으로 조정
📌 Idle Session이 CPU 사용률을 증가시킴.
→ 추가로 더 보면 좋은 내용 "Resources consumed by idle PostgreSQL connections"
'PostgreSQL' 카테고리의 다른 글
| PostgreSQL - Memory - Shared Buffer (0) | 2025.02.22 |
|---|---|
| PostgreSQL - Memory - Backend Buffer (0) | 2025.02.22 |
| PostgreSQL Architecture (0) | 2025.02.22 |
| PostgreSQL Query Optimization : 실행 계획 - Scan 방식의 종류 (0) | 2024.12.29 |
| PostgreSQL Query Optimization : 실행 계획 이해하기 (0) | 2024.12.21 |