Oracle ORA-04030 오류 원인과 해결 방법 완벽 가이드

ORA-04030
2026년 08월 20일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-04030 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-04030 out of process memory when trying to allocate bytes 는?

ORA-04030 에러는 Oracle 프로세스가 메모리를 추가로 할당하려 할 때 운영체제(OS)로부터 더 이상 메모리를 받을 수 없는 상황에서 발생합니다. 이 에러는 PGA(Program Global Area) 또는 UGA(User Global Area) 메모리가 부족할 때 나타나며, 주로 대용량 정렬 작업, 해시 조인, PL/SQL 컬렉션 처리 등 메모리 집약적인 작업에서 발생합니다. 단순히 Oracle 설정의 문제가 아닌 OS 레벨의 메모리 고갈, Oracle 파라미터 설정 오류, 또는 비효율적인 SQL/PL/SQL 코드가 복합적으로 작용하여 발생하는 경우가 많습니다.


주요 발생 원인

1. PGA_AGGREGATE_TARGET 또는 PGA_AGGREGATE_LIMIT 설정 부족

Oracle의 PGA 메모리 관리 파라미터가 너무 낮게 설정되어 있으면, 대용량 정렬이나 해시 조인 수행 시 개별 프로세스에 할당할 수 있는 메모리 한도를 초과하게 됩니다. 특히 PGA_AGGREGATE_LIMIT은 Oracle 12c부터 도입된 파라미터로, 전체 PGA 사용량에 Hard Limit을 걸기 때문에 이 값이 너무 작으면 ORA-04030이 빈번하게 발생합니다. 운영 환경에서 동시 접속자가 급증하거나 배치 작업이 겹치는 시간대에 이 문제가 특히 심화됩니다.

2. 비효율적인 SQL로 인한 과도한 메모리 소비

실행 계획이 최적화되지 않은 SQL 문장은 필요 이상의 PGA 메모리를 소모합니다. 예를 들어, 인덱스를 사용하지 않는 대규모 Full Table Scan 후 정렬(ORDER BY, GROUP BY)을 수행하거나, 불필요하게 큰 IN-LIST를 사용하는 쿼리는 Sort Area와 Hash Area를 과도하게 점유합니다. 또한 커서를 닫지 않거나 PL/SQL에서 BULK COLLECT를 무제한으로 사용하면 세션 메모리가 지속적으로 누적되어 결국 ORA-04030을 유발합니다.

3. OS 레벨의 메모리 부족 및 가상 메모리 제한

Oracle 프로세스가 사용할 수 있는 메모리는 궁극적으로 OS가 허용하는 범위 내에 있습니다. Linux/Unix 환경에서는 ulimit 설정의 virtual memory (v) 또는 data segment size (d) 값이 너무 작게 설정되어 있거나, 서버 전체의 물리 메모리와 스왑 공간이 고갈된 경우 Oracle이 메모리를 요청해도 OS가 이를 거부하게 됩니다. 또한 NUMA(Non-Uniform Memory Access) 아키텍처 환경에서 메모리 노드 불균형이 발생했을 때도 특정 프로세스가 메모리 할당에 실패할 수 있습니다.


해결 방법

원인 1 해결: PGA 파라미터 조정

현재 PGA 사용 현황을 먼저 확인합니다.

-- 현재 PGA 사용 현황 확인
SELECT name, value/1024/1024 AS value_mb
FROM v$pgastat
WHERE name IN (
    'aggregate PGA target parameter',
    'aggregate PGA auto target',
    'global memory bound',
    'total PGA inuse',
    'total PGA allocated',
    'maximum PGA allocated'
);

-- 세션별 PGA 사용량 상위 10개 조회
SELECT s.sid,
       s.serial#,
       s.username,
       s.program,
       p.pga_used_mem   / 1024 / 1024 AS pga_used_mb,
       p.pga_alloc_mem  / 1024 / 1024 AS pga_alloc_mb,
       p.pga_max_mem    / 1024 / 1024 AS pga_max_mb
FROM   v$session s
JOIN   v$process p ON s.paddr = p.addr
WHERE  s.username IS NOT NULL
ORDER  BY p.pga_alloc_mem DESC
FETCH FIRST 10 ROWS ONLY;

현황 확인 후 파라미터를 조정합니다.

-- PGA_AGGREGATE_TARGET 조정 (물리 메모리의 20% 권장)
ALTER SYSTEM SET PGA_AGGREGATE_TARGET = 4096M SCOPE=BOTH;

-- PGA_AGGREGATE_LIMIT 조정 (PGA_AGGREGATE_TARGET의 2배 권장)
ALTER SYSTEM SET PGA_AGGREGATE_LIMIT = 8192M SCOPE=BOTH;

-- 변경 후 확인
SHOW PARAMETER PGA;

원인 2 해결: 비효율 SQL 튜닝 및 PL/SQL 메모리 관리

-- 과도한 PGA를 소비하는 SQL 식별
SELECT sql_id,
       sql_text,
       sharable_mem / 1024 / 1024   AS sharable_mb,
       persistent_mem / 1024 / 1024AS persistent_mb,
       runtime_mem / 1024 / 1024    AS runtime_mb,
       executions,
       sorts,
       hash_misses
FROM   v$sql
WHERE  runtime_mem > 10 * 1024 * 1024  -- 10MB 이상 소비 SQL
ORDER  BY runtime_mem DESC
FETCH FIRST 20 ROWS ONLY;

-- WORKAREA 사용 현황 확인 (Disk로 넘어간 경우 튜닝 필요)
SELECT operation_type,
       policy,
       SUM(estimated_optimal_size)/1024/1024  AS optimal_mb,
       SUM(last_memory_used)/1024/1024        AS last_used_mb,
       SUM(total_executions)                  AS total_exec,
       SUM(optimal_executions)                AS optimal_exec,
       SUM(onepass_executions)                AS onepass_exec,
       SUM(multipasses_executions)            AS multipass_exec
FROM   v$sql_workarea_histogram
GROUP  BY operation_type, policy
ORDER  BY operation_type;

PL/SQL에서 BULK COLLECT 사용 시 LIMIT을 반드시 지정합니다.

-- 잘못된 방법 (메모리 폭증 위험)
-- BULK COLLECT INTO collection_var; -- LIMIT 없음

-- 올바른 방법 (LIMIT으로 메모리 제어)
DECLARE
    TYPE emp_tbl_type IS TABLE OF employees%ROWTYPE;
    l_emp_tbl emp_tbl_type;
    CURSOR c_emp IS SELECT * FROM employees WHERE department_id = 10;
BEGIN
    OPEN c_emp;
    LOOP
        FETCH c_emp BULK COLLECT INTO l_emp_tbl LIMIT 1000; -- 1,000건씩 처리
        EXIT WHEN l_emp_tbl.COUNT = 0;
        -- 처리 로직
        FORALL i IN 1..l_emp_tbl.COUNT
            UPDATE emp_log SET processed = 'Y'
            WHERE  employee_id = l_emp_tbl(i).employee_id;
        COMMIT;
        l_emp_tbl.DELETE; -- 메모리 명시적 해제
    END LOOP;
    CLOSE c_emp;
END;
/

원인 3 해결: OS 레벨 설정 확인 및 조정

-- Oracle 프로세스 OS PID 확인
SELECT p.spid, s.sid, s.serial#, s.username, s.program,
       p.pga_used_mem/1024/1024 AS pga_used_mb
FROM   v$process p
JOIN   v$session s ON p.addr = s.paddr
WHERE  s.username IS NOT NULL
ORDER  BY p.pga_used_mem DESC
FETCH FIRST 5 ROWS ONLY;

OS 레벨에서 ulimit 및 메모리 확인 (Linux 기준):

# Oracle OS 사용자의 ulimit 확인
ulimit -a

# 가상 메모리 제한 해제 (oracle 계정 /etc/security/limits.conf)
# oracle soft memlock unlimited
# oracle hard memlock unlimited
# oracle soft as unlimited
# oracle hard as unlimited

# 현재 메모리 사용량 확인
free -m
vmstat -s

예방 방법

1. AWR/ASH 기반 PGA 사용 추세 모니터링 자동화

주기적으로 PGA 사용 현황을 모니터링하여 임계치 초과 시 자동으로 경고를 받을 수 있는 체계를 구축해야 합니다. Oracle Enterprise Manager(OEM)의 Metric 알림을 활용하거나, 아래 쿼리를 Cron Job 형태로 스케줄링하여 PGA 사용량이 설정값의 80%를 초과할 때 DBA에게 알림을 발송하는 방식을 권장합니다.

-- AWR에서 PGA 사용 이력 확인 (최근 7일)
SELECT TO_CHAR(s.begin_interval_time, 'YYYY-MM-DD HH24') AS snap_hour,
       ROUND(AVG(m.value) / 1024 / 1024, 2)             AS avg_pga_mb,
       ROUND(MAX(m.value) / 1024 / 1024, 2)             AS max_pga_mb
FROM   dba_hist_pgastat m
JOIN   dba_hist_snapshot s ON m.snap_id = s.snap_id
                           AND m.dbid   = s.dbid
                           AND m.instance_number = s.instance_number
WHERE  m.name = 'maximum PGA allocated'
  AND  s.begin_interval_time >= SYSDATE - 7
GROUP  BY TO_CHAR(s.begin_interval_time, 'YYYY-MM-DD HH24')
ORDER  BY 1;

2. 개발 단계에서의 SQL 검토 프로세스 의무화

운영 환경 배포 전에 신규 SQL 및 PL/SQL 코드에 대한 실행 계획(Execution Plan) 검토와 DBMS_XPLAN, V$SQL_WORKAREA를 활용한 메모리 사용량 분석을 개발 게이트로 의무화해야 합니다. 특히 Full Table Scan이 예상되는 대용량 테이블에 대한 쿼리는 반드시 파티션 프루닝, 적절한 인덱스 사용 여부, BULK COLLECT LIMIT 설정 등을 코드 리뷰 체크리스트에 포함시키는 것이 중요합니다.


관련 에러

  • ORA-04031: Shared Pool 또는 Large Pool의 메모리 부족 에러로, ORA-04030이 PGA(프로세스 메모리)의 문제라면 ORA-04031은 SGA의 공유 메모리 영역 부족을 나타냅니다. 두 에러가 동시에 발생한다면 서버 전체의 메모리 증설을 검토해야 합니다.
  • ORA-01555: 메모리 압박으로 인해 대용량 트랜잭션이 지연될 때 Undo Segment 부족과 함께 동반 발생할 수 있습니다.
  • ORA-27102: OS 레벨에서 메모리 할당 자체가 실패할 때 발생하며, ORA-04030과 함께 Alert Log에 기록되는 경우 OS 설정 점검이 우선입니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기