[PostgreSQL] 서버 재시작하지 않고 무중단으로 SWAP 메모리 초기화 하는 방법 & 이슈 대처 방법 포함
swap 메모리가 올라가는 이유는?
Swap 메모리가 올라가는 근본적인 이유는 물리 메모리(RAM)가 일시적이든 지속적이든 부족했기 때문이며, 리눅스 커널이 시스템을 유지하기 위해 RAM의 데이터를 디스크(Swap)로 옮겼기 때문입니다.
조금 더 구체적으로 DB 서버에서 Swap이 차오르는 핵심 이유는 다음과 같습니다.
1. 순간적인 메모리 유입량 초과 (가장 흔함)
- 평소에는 RAM 사용량(
MEM Used)이 28% 수준으로 낮아 보이지만, 특정 시간대에 무거운 배치 작업(Batch), 대규모 조회(Select) 쿼리, 혹은 동시 접속자(Connection)가 급증했을 수 있습니다. - 이 순간 RAM이 일시적으로 100% 가까이 차오르면, 리눅스 커널은 당장 급한 작업에 RAM을 주려고 “지금 당장 일 안 하고 노는 프로세스의 데이터”를 Swap 공간으로 쫓아냅니다.
- 이후 트래픽이 빠져나가서 RAM 사용량이 다시 28%로 내려가더라도, Swap으로 한 번 쫓겨난 데이터는 다시 누군가 강제로 요청하기 전까지는 RAM으로 자동 복귀하지 않고 Swap에 그대로 박혀있게 됩니다. 이 때문에 겉보기에는 RAM이 널널한데 Swap만 높게 유지되는 현상이 발생합니다.
2. 리눅스의 기본 메모리 관리 정책 (swappiness)
- 리눅스는 RAM이 남아있더라도 “자주 안 쓰는 데이터는 차라리 Swap에 보관하고, 남는 RAM 공간을 디스크 캐시(
buff/cache)로 활용하여 서버 전체 파일 읽기 속도를 높이는 게 이득이다”라고 판단하도록 기본 설정(기본값 60)되어 있습니다. - 이 설정 때문에 DB 서버처럼 파일 읽기/쓰기가 많은 환경에서는 시간이 지날수록 Swap이 야금야금 차오르게 됩니다.
무중단으로 SWAP 메모리 초기화 하는 방법
DB 서버를 재기동하지 않고 Swap 메모리를 정리하려면 물리 메모리(RAM)의 여유 공간을 확보한 후 Swap을 비활성화했다가 다시 활성화해야 합니다.
단, Swap 정리 작업 중에는 순간적으로 RAM 사용량이 급증하므로, 반드시 실제 여유 메모리(Free RAM)가 현재 사용 중인 Swap 용량보다 큰지 확인한 후 진행해야 합니다.
1단계: 메모리 상태 상세 확인 (반드시 선행)
터미널에서 아래 명령어를 입력하여 현재 실제 남은 RAM 용량과 Swap 사용 용량을 Byte 단위로 정확히 비교합니다.
free -h

주의 조건: free 또는 available 메모리가 현재 사용 중인 Swap 메모리 크기보다 더 커야 2단계 작업을 안전하게 진행할 수 있습니다.
2단계: 캐시 메모리 비우기 (선택 사항이지만 권장)
Swap에 있는 데이터를 RAM으로 가져오기 전에, RAM을 최대한 확보하기 위해 버퍼와 페이지 캐시를 정리합니다. (DB 서비스에 영향을 주지 않는 안전한 명령입니다.)
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
하지만 대용량 DB 서버나 디스크 I/O가 빈번한 운영 환경에서는 순간적으로 서비스 성능이 크게 저하되는 부작용이 발생할 수 있습니다. 발생 가능한 구체적인 상황과 리스크는 다음과 같습니다.
1. 순간적인 CPU 및 디스크 I/O 부하 급증
echo 3명령을 내리면 커널은 메모리에 있던 파일 캐시(Page Cache)를 비우기 전에 디스크와 동기화되지 않은 데이터를 먼저 디스크에 기록(sync)해야 합니다.- 이 과정에서 디스크 쓰기(Write) 작업이 순간적으로 몰리면서 디스크 I/O 수치가 100%까지 치솟을 수 있습니다. 이로 인해 서비스의 쿼리 응답 속도가 일시적으로 느려질 수 있습니다.
2. Read 쿼리 처리 속도 저하 (Cache Miss)
- DB 서버는 자주 조회하는 데이터를 메모리(캐시)에 올려두고 빠르게 응답합니다. 하지만 캐시를 강제로 비워버리면, 이후 들어오는 조회 요청들은 메모리가 아닌 느린 물리 디스크에서 직접 데이터를 읽어와야 합니다(Cache Miss).
- 캐시가 다시 채워질 때까지(Warm-up 기간) 쿼리 수행 시간이 평소보다 길어질 수 있으며, 이 동안 사용자가 서비스 지연을 느낄 수 있습니다.
3. 명령어 실행 지연 (수 초~수 분 대기)
- 메모리에 쌓여있는 캐시 용량이 클수록(현재 서버는 5.4GiB로 다소 많은 편입니다) 이를 정리하고 디스크에 쓰는 데 시간이 걸립니다.
- 명령어를 엔터 치고 나서 바로 프롬프트가 떨어지지 않고, 몇 초에서 길게는 1~2분간 멈춰있는 것처럼 보일 수 있습니다. 이는 락이 걸린 것이 아니라 커널이 내부적으로 메모리를 정리하는 중이므로 강제로 취소(
Ctrl + C)하지 말고 기다리셔야 합니다.
리스크를 최소화하며 안전하게 수행하는 방법
현재 운영 중인 DB 서버의 트래픽이 몰리는 시간대라면 즉시 실행하는 것은 피하는 것이 좋습니다. 아래 가이드를 참고해 주세요.
- 동접자가 적은 시간대(새벽 또는 점검 시간)에 수행하는 것이 가장 안전합니다.
echo 3대신echo 1을 먼저 시도해 볼 수 있습니다.1: 페이지 캐시(파일 읽기/쓰기 캐시)만 비우기 ➔ DB 서버에서 가장 효과적이며 리스크가 적음2: inode 및 dentry 캐시(디렉토리 구조 캐시)만 비우기3: 1번과 2번을 모두 비우기
sudo sync && echo 1 | sudo tee /proc/sys/vm/drop_caches
---------------------------------------------------------
명령어의 구성 요소를 뜯어보면 다음과 같습니다:
• sudo sync: 메모리에만 남아있던 변경된 파일 데이터를 물리 디스크에 즉시 안전하게 기록(동기화)합니다. 로키 리눅스의 필수 명령어입니다.
• &&: 앞의 sync 작업이 에러 없이 무사히 완료되면 뒤의 명령어를 실행하라는 뜻입니다.
• echo 1: 커널에 '페이지 캐시만 비워라'라는 신호(값 1)를 보냅니다.
• | sudo tee ...: 일반 관리자 권한 권한 분리 장치입니다. /proc/sys/ 경로는 보안상 sudo echo 1 > ... 방식으로 직접 쓰기가 안 되기 때문에, tee 명령어를 조합하여 안전하게 값을 입력하는 리눅스 표준 표준 표준 표준 기법입니다
echo 1만 실행해도 현재 부족한free메모리는 충분히 확보될 가능성이 높습니다.
- 종료 후 free -h명령어로 확보된 가용 메모리를 확인합니다.
3단계: Swap 끄고 다시 켜기 (초기화 핵심)
Swap을 오프라인으로 전환하면 리눅스 커널이 Swap에 있던 데이터를 물리 메모리(RAM)로 모두 이동시킵니다. 이동이 완료되면 Swap이 0%로 초기화됩니다. 이후 다시 Swap을 켭니다.
# 1. Swap 비활성화 (데이터를 RAM으로 이동, 수 분 소요될 수 있음)
sudo swapoff -a
- 절대 창을 닫거나
Ctrl + C를 누르지 말고 끝까지 기다려 주세요.

- 참고:
swapoff명령을 내리면 데이터 이동을 위해 잠시 터미널이 대기 상태(블로킹)가 됩니다. 작업이 끝날 때까지 창을 닫지 마세요. swapoff -a명령어를 실행하는 동안, 다른 터미널 창을 하나 더 열어서vmstat 1또는top명령어로 메모리가 잘 이동하고 있는지 실시간으로 모니터링하는 것을 권장합니다.
# 2. Swap 다시 활성화
sudo swapon -a

sudo swapoff -a를 실행하면 Swap에 있던 데이터(약 1.6GiB)가 그대로 RAM으로 밀려 들어오기 때문에, RAM 사용량(Used)이 즉시 그만큼 껑충 올라가게 됩니다.
이 올라간 RAM 사용량이 언제, 어떻게 내려가는지에 대한 메커니즘은 다음과 같습니다.
1. 자동으로 바로 내려가지는 않습니다 (리눅스의 메모리 보존 정책)
리눅스 커널은 한 번 RAM에 로드된 데이터를 일부러 먼저 지우지 않습니다. “나중에 또 쓸 수도 있으니까 일단 RAM에 보관하자”라는 정책을 쓰기 때문입니다. 따라서 Swap을 비운 직후 올라간 RAM 사용량은 아무런 작업도 하지 않으면 그 상태 그대로 계속 유지됩니다.
2. RAM 사용량이 다시 내려가는 시점 (3가지 케이스)
올라간 RAM 사용량은 다음과 같은 상황이 발생할 때 자연스럽게 내려갑니다.
- PostgreSQL 내부 세션/커넥션이 종료될 때 (가장 큼): Swap에 있던 데이터의 대부분은 과거에 무거운 쿼리를 날렸던 사용자의 연결 세션이거나 임시 작업 공간 데이터입니다. 웹 애플리케이션이나 개발자들이 DB 연결을 끊거나, 일정 시간 유휴 상태(Idle)가 되어 DB 세션이 종료되는 시점에 해당 메모리가 운영체제(OS)로 반환되면서 RAM 사용량이 뚝 떨어집니다.
- 새로운 대용량 작업이 들어와 RAM이 진짜로 필요해질 때: 다른 프로세스가 대용량 RAM을 요구하면, 커널은 현재 RAM에 있는 데이터 중 “오랫동안 쓰지 않은 데이터”를 스스로 판단하여 메모리에서 해제(Free)해 버립니다.
- DB 서비스를 재기동할 때 (인위적인 초기화): 정기 점검 등 추후에 PostgreSQL 서비스를 재기동(
systemctl restart postgresql)하게 되면, DB가 붙잡고 있던 모든 메모리가 일시에 완전히 청소되면서 RAM 사용량이 초기 상태로 완전히 내려갑니다.
💡 향후 재발 방지를 위한 팁: vm.swappiness 조절
리눅스는 RAM이 남아있어도 특정 상황에서 Swap을 적극적으로 사용하려는 경향이 있습니다. 특히 DB 서버에서는 Swap을 최소화하는 것이 성능에 좋습니다.
Swap 초기화가 모두 끝난 후, 다음 트래픽 급증 시 또 Swap이 차오르는 것을 막으려면 RAM이 90% 이상 거의 꽉 찼을 때만 Swap을 쓰도록 정책을 바꿔야 합니다.
1.현재 설정 값 확인 (기본값은 대개 60)
cat /proc/sys/vm/swappiness
2.임시로 값을 10으로 변경 (RAM이 거의 가득 찼을 때만 Swap을 쓰도록 설정)
sudo sysctl vm.swappiness=10
- 서버 재부팅시 원래 값으로 되돌아갑니다.
3.영구 반영 (/etc/sysctl.conf 파일 맨 아래에 추가)
vm.swappiness = 10
또는
# 파일 맨 아래에 설정값을 추가하는 명령어입니다.
echo "vm.swappiness = 10" | sudo tee -a /etc/sysctl.conf
만약 작업 중 PostgreSQL이 중단되었다면?
아래 명령어로 즉시 복구합니다. 로키 리눅스(Rocky Linux)에서 PostgreSQL 서비스를 즉각 제어하고 모니터링하는 명령어 세트입니다.
1. PostgreSQL 즉각 재기동 명령어
# 기본 서비스명으로 시작
sudo systemctl start postgresql
# 버전이 지정된 서비스명으로 시작 (버전에 맞게 숫자 변경)
sudo systemctl start postgresql-14
- 만약 서비스명을 찾을 수 없다는 에러(
Failed to start postgresql.service: Unit not found.)가 발생하면, 아래와 같이 버전 숫자가 포함된 서비스명을 사용해야 합니다.
(예: PostgreSQL 14 버전인 경우)
2. 정상 작동 여부 확인 (필수)
서비스를 시작한 후, 실제로 잘 구동되어 연결을 받고 있는지 반드시 상태를 확인해야 합니다.
# 서비스 상태 확인
sudo systemctl status postgresql
# (또는 버전에 맞게)
sudo systemctl status postgresql-14
- 화면에 초록색 글씨로
Active: active (running)이라고 표시되면 정상적으로 복구된 것입니다.
3. 죽은 원인 및 에러 로그 즉시 확인
만약 위의 start 명령어를 내렸는데도 에러가 나면서 켜지지 않는다면, 시스템 저널 로그를 통해 최근 50줄의 에러 기록을 바로 확인합니다.
sudo journalctl -u postgresql -n 50 --no-pager
# (또는 버전에 맞게)
sudo journalctl -u postgresql-15 -n 50 --no-pager




