2026년 09월 23일 | DBMS Error 가이드
이 글에서 다루는 내용
58000 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
58000 system error 는?
PostgreSQL 에러 코드 58000 (system error) 는 데이터베이스 서버가 운영체제 수준의 시스템 호출(system call)을 실행하는 과정에서 예기치 않은 실패가 발생했을 때 반환되는 에러입니다. 이 에러는 SQL 쿼리 자체의 논리적 문제가 아닌, 파일 시스템, 메모리, 네트워크 소켓, 프로세스 간 통신(IPC) 등 서버 인프라 레벨의 문제에서 기인합니다. 주로 디스크 공간 부족, 파일 권한 오류, 소켓 연결 실패, 혹은 운영체제 리소스 고갈 상황에서 발생하며, 애플리케이션 개발자보다 DBA 또는 시스템 관리자 수준의 개입이 필요한 심각한 에러입니다.
주요 발생 원인
1. 디스크 공간 부족 또는 파일 시스템 오류
PostgreSQL은 데이터 파일, WAL(Write-Ahead Log), 임시 파일 등을 지속적으로 디스크에 기록합니다. 디스크가 가득 차거나 파일 시스템에 I/O 오류가 발생하면, 운영체제의 write() 또는 fsync() 시스템 콜이 실패하면서 58000 에러가 트리거됩니다. 특히 대용량 트랜잭션이나 VACUUM 작업 중에 이 상황이 자주 발생하며, 데이터 손상으로 이어질 수 있는 가장 위험한 원인 중 하나입니다.
2. Unix Domain Socket 또는 네트워크 소켓 통신 실패
PostgreSQL의 백엔드 프로세스와 클라이언트, 혹은 내부 프로세스 간의 소켓 통신이 실패할 때 이 에러가 발생합니다. /var/run/postgresql/ 디렉토리의 Unix 소켓 파일에 대한 접근 권한 문제, 소켓 파일 손상, 또는 max_connections 초과로 인해 새로운 소켓을 생성하지 못하는 경우에도 해당 에러가 발생할 수 있습니다. 특히 컨테이너 환경(Docker, Kubernetes)에서 소켓 마운트 설정이 잘못된 경우 빈번히 나타납니다.
3. 운영체제 리소스 한계 초과 (ulimit, shared memory)
PostgreSQL은 공유 메모리(shared memory), 세마포어(semaphore), 파일 디스크립터(file descriptor) 등 다양한 OS 리소스를 사용합니다. ulimit 설정이 지나치게 낮거나, shared_buffers 또는 max_connections 설정이 OS의 shmmax, shmall 한계를 초과하면 시스템 콜이 실패하면서 58000 에러로 이어집니다. 이 문제는 서버 재시작 직후 또는 트래픽이 급증하는 피크 타임에 주로 발견됩니다.
해결 방법
원인 1 해결: 디스크 공간 확보 및 파일 시스템 점검
먼저 현재 디스크 사용량을 확인하고 PostgreSQL 데이터 디렉토리의 공간을 점검합니다.
-- PostgreSQL 내부에서 데이터베이스별 크기 확인
SELECT
datname AS database_name,
pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
ORDER BY pg_database_size(datname) DESC;
-- 가장 큰 테이블 TOP 10 확인
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 10;
-- 임시 파일 사용량 확인 (pg_stat_database)
SELECT
datname,
temp_files,
pg_size_pretty(temp_bytes) AS temp_size
FROM pg_stat_database
WHERE temp_bytes > 0
ORDER BY temp_bytes DESC;
디스크 공간이 부족한 경우, 불필요한 테이블을 정리하거나 오래된 WAL 파일을 아카이빙 후 제거합니다.
-- 불필요한 bloat 제거를 위한 VACUUM FULL (주의: 테이블 잠금 발생)
VACUUM FULL ANALYZE large_table_name;
-- 오래된 파티션 테이블 삭제 예시
DROP TABLE IF EXISTS logs_2022_01;
-- work_mem을 줄여 임시 파일 과다 생성 방지 (세션 레벨)
SET work_mem = '64MB';
원인 2 해결: 소켓 및 연결 문제 해결
-- 현재 활성 연결 수 및 상태 확인
SELECT
state,
count(*) AS connection_count,
max(now() - state_change) AS max_idle_time
FROM pg_stat_activity
GROUP BY state
ORDER BY connection_count DESC;
-- 오래된 idle 연결 강제 종료 (PostgreSQL 9.2+)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
AND state_change < now() - INTERVAL '30 minutes'
AND pid <> pg_backend_pid();
-- 연결 한도 설정 확인
SHOW max_connections;
-- 특정 데이터베이스의 연결 한도 조정
ALTER DATABASE mydb CONNECTION LIMIT 100;
소켓 파일 문제는 서버 외부에서 확인합니다.
# 소켓 파일 존재 여부 확인
ls -la /var/run/postgresql/.s.PGSQL.5432
# PostgreSQL 서비스 재시작 (소켓 재생성)
sudo systemctl restart postgresql
# 소켓 디렉토리 권한 확인
stat /var/run/postgresql/
원인 3 해결: OS 리소스 한계 조정
-- 현재 shared_buffers 및 주요 메모리 설정 확인
SHOW shared_buffers;
SHOW max_connections;
SHOW work_mem;
-- pg_settings에서 메모리 관련 설정 전체 확인
SELECT name, setting, unit, context
FROM pg_settings
WHERE name IN (
'shared_buffers',
'effective_cache_size',
'work_mem',
'maintenance_work_mem',
'max_connections'
);
OS 레벨에서 ulimit 및 shared memory 설정을 조정합니다.
-- postgresql.conf에서 설정 변경 후 적용 여부 확인
SELECT pg_reload_conf();
-- 변경된 설정이 적용되었는지 검증
SELECT name, setting, pending_restart
FROM pg_settings
WHERE pending_restart = true;
예방 방법
1. 디스크 및 리소스 모니터링 자동화
PostgreSQL 서버의 디스크 사용량, 연결 수, 메모리 사용량을 실시간으로 모니터링하는 체계를 반드시 구축해야 합니다. Prometheus + pg_exporter, Grafana, 또는 Zabbix 같은 도구를 활용하여 디스크 사용률이 70%를 초과하거나 연결 수가 max_connections의 80%에 도달할 경우 즉시 알람이 발송되도록 설정하세요. 또한 주기적으로 pg_stat_activity, pg_stat_bgwriter, pg_stat_database 뷰를 조회하는 모니터링 쿼리를 cron job으로 등록하여 이상 징후를 사전에 포착하는 것이 중요합니다.
-- 모니터링용 주요 지표 쿼리 (cron job으로 주기적 실행 권장)
SELECT
now() AS checked_at,
(SELECT count(*) FROM pg_stat_activity) AS total_connections,
(SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS max_connections,
(SELECT count(*) FROM pg_stat_activity WHERE state = 'active') AS active_queries,
(SELECT count(*) FROM pg_stat_activity WHERE wait_event_type = 'Lock') AS waiting_on_lock;
2. Connection Pooling 및 리소스 한계 사전 설계
애플리케이션과 PostgreSQL 사이에 PgBouncer 또는 Pgpool-II 같은 커넥션 풀러를 배치하면 갑작스러운 연결 폭증으로 인한 소켓 및 리소스 고갈을 효과적으로 방지할 수 있습니다. postgresql.conf의 max_connections는 실제 운영 환경에서 필요한 값보다 20~30% 여유를 두고 설정하되, OS의 ulimit -n(파일 디스크립터 수)과 kernel.shmmax 값이 PostgreSQL 설정과 일관성을 갖도록 사전에 용량 계획(capacity planning)을 수행해야 합니다.
관련 에러
- 53100 (disk_full): 디스크가 완전히 가득 찼을 때 발생하는 에러로, 58000의 원인 중 하나입니다. 58000보다 더 구체적인 디스크 관련 에러입니다.
- 53200 (out_of_memory): 운영체제 또는 PostgreSQL 프로세스가 메모리를 할당하지 못할 때 발생하며, 58000과 유사한 시스템 레벨 문제입니다.
- 57P03 (cannot_connect_now): 서버가 시작 중이거나 셧다운 중일 때 연결을 거부하는 에러로, 소켓 문제와 함께 발생하는 경우가 있습니다.
- 08006 (connection_failure): 연결이 예기치 않게 끊어질 때 발생하며, 58000으로 인한 서버 충돌 이후 클라이언트 측에서 경험할 수 있는 에러입니다.
- XX000 (internal_error): PostgreSQL 내부의 예상치 못한 상태를 나타내며, 58000과 함께 로그에 동시에 기록되는 경우가 많습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.