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

ORA-04061
2026년 08월 22일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-04061 existing state has been invalidated 는?

ORA-04061 에러는 Oracle 데이터베이스에서 패키지(Package), 프로시저(Procedure), 함수(Function), 트리거(Trigger) 등의 PL/SQL 객체가 컴파일된 이후, 해당 객체가 참조하는 다른 객체가 변경(ALTER, DROP, REPLACE 등)되어 기존 상태(State)가 무효화(Invalidate)될 때 발생합니다. 쉽게 말해, 세션이 특정 패키지나 객체를 메모리에 올려서 사용하는 도중에 그 객체의 상태가 바뀌었을 때 Oracle이 이 에러를 발생시키는 것입니다. 이 에러는 주로 운영 중인 시스템에 DDL 변경 작업이 발생할 때 기존 세션에서 자주 마주치게 되며, 에러 발생 후 해당 객체를 재호출하면 Oracle이 자동으로 재컴파일을 시도하여 대부분의 경우 정상 동작으로 복구됩니다.


주요 발생 원인

1. 패키지 또는 의존 객체의 재컴파일(Recompile) 또는 재생성(Replace)

가장 흔한 원인으로, 운영 중인 시스템에서 DBA 또는 개발자가 패키지 바디(Package Body)나 패키지 스펙(Package Spec)을 수정하여 재컴파일하거나 CREATE OR REPLACE를 실행할 때 발생합니다. 이미 해당 패키지를 세션 메모리에 로드하여 사용 중인 기존 세션은 패키지 상태가 무효화되었음을 인식하고 ORA-04061을 반환합니다. 특히 패키지 스펙이 변경되는 경우, 해당 패키지에 의존하는 모든 다른 패키지와 객체도 연쇄적으로 INVALID 상태가 될 수 있어 영향 범위가 매우 넓어질 수 있습니다.

2. 패키지가 참조하는 테이블, 뷰, 시노님(Synonym) 등 DB 객체의 변경

패키지나 프로시저가 내부적으로 참조하는 테이블에 컬럼이 추가/삭제되거나 뷰가 재생성되거나 시노님의 대상이 변경될 경우에도 이 에러가 발생합니다. Oracle의 의존성 추적 메커니즘은 매우 정밀하게 작동하여, 참조 객체의 정의가 변경되면 상위 PL/SQL 객체를 자동으로 INVALID 상태로 표시합니다. 이 경우 단순히 재호출로는 해결되지 않을 수 있으며, 명시적인 재컴파일이 필요할 수 있습니다.

3. 패키지 변수(Package-Level Variable)의 상태 불일치

패키지 스펙 또는 바디에 전역 변수(Global Variable)나 커서(Cursor)가 선언되어 있는 경우, 해당 패키지가 재컴파일되면 기존 세션이 가지고 있던 패키지 변수 상태가 모두 초기화됩니다. 이때 Oracle은 세션의 기존 패키지 인스턴스 상태가 무효화되었음을 알리기 위해 ORA-04061을 발생시키며, 연속적으로 ORA-04065, ORA-06508 에러가 함께 나타나는 경우가 많습니다. Stateful 패키지를 사용하는 애플리케이션에서는 이 에러가 특히 치명적으로 작용할 수 있습니다.


해결 방법

원인 1: 패키지 재컴파일로 인한 에러 해결

기존 세션에서 에러가 발생한 경우, 가장 간단한 해결책은 애플리케이션 또는 세션을 재시작하는 것입니다. 새로운 세션은 재컴파일된 최신 패키지를 로드하므로 에러 없이 정상 동작합니다. 또한 DBA는 배포 후 명시적으로 재컴파일을 수행하여 INVALID 상태의 객체를 정리해야 합니다.

-- 특정 패키지를 명시적으로 재컴파일
ALTER PACKAGE my_package COMPILE;
ALTER PACKAGE my_package COMPILE BODY;

-- 특정 스키마 내 모든 INVALID 객체 일괄 재컴파일 (UTL_RECOMP 사용)
EXEC UTL_RECOMP.RECOMP_SERIAL('MY_SCHEMA');

-- 병렬 재컴파일 (대규모 환경에서 권장)
EXEC UTL_RECOMP.RECOMP_PARALLEL(4, 'MY_SCHEMA');

-- INVALID 상태 객체 현황 조회
SELECT object_name, object_type, status, last_ddl_time
FROM   dba_objects
WHERE  status = 'INVALID'
ORDER  BY last_ddl_time DESC;

원인 2: 참조 객체 변경 후 의존성 재컴파일

테이블이나 뷰 등 참조 객체가 변경된 경우, 영향받는 모든 PL/SQL 객체를 재컴파일해야 합니다. Oracle이 제공하는 $ORACLE_HOME/rdbms/admin/utlrp.sql 스크립트를 활용하면 전체 데이터베이스의 INVALID 객체를 한 번에 재컴파일할 수 있습니다.

-- 특정 객체에 의존하는 PL/SQL 객체 목록 조회
SELECT d.name        AS dependent_object,
       d.type        AS dependent_type,
       r.name        AS referenced_object,
       r.type        AS referenced_type
FROM   dba_dependencies d
JOIN   dba_dependencies r
       ON d.referenced_name = r.name
WHERE  d.referenced_name = 'MY_TABLE'  -- 변경된 테이블명 입력
  AND  d.type IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER');

-- 테이블 컬럼 추가 후 의존 패키지 재컴파일 예시
ALTER TABLE my_table ADD (new_column VARCHAR2(100));

-- 이후 의존 객체 재컴파일
ALTER PACKAGE my_package COMPILE BODY;

-- 전체 DB INVALID 객체 재컴파일 (SYS로 실행)
@$ORACLE_HOME/rdbms/admin/utlrp.sql

원인 3: Stateful 패키지 에러 처리 (애플리케이션 레벨)

Stateful 패키지를 사용하는 경우, 애플리케이션 코드에서 ORA-04061 예외를 잡아서 세션을 재초기화하는 로직을 구현하는 것이 좋습니다.

-- ORA-04061 에러 핸들링 예시 프로시저
CREATE OR REPLACE PROCEDURE safe_call_example AS
  v_result VARCHAR2(200);
BEGIN
  -- 패키지 함수 호출 시도
  v_result := my_package.get_data(p_id => 1);
  DBMS_OUTPUT.PUT_LINE('결과: ' || v_result);
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE IN (-4061, -4065, -4068) THEN
      -- ORA-04061/04065/04068 발생 시 패키지 상태 초기화 후 재시도
      DBMS_OUTPUT.PUT_LINE('패키지 상태 무효화 감지. 재시도 중...');
      -- 실제 환경에서는 세션 재연결 또는 패키지 초기화 로직 수행
      v_result := my_package.get_data(p_id => 1);
      DBMS_OUTPUT.PUT_LINE('재시도 결과: ' || v_result);
    ELSE
      RAISE;
    END IF;
END safe_call_example;
/

-- 패키지 상태 무효화 여부 사전 확인 쿼리
SELECT package_name,
       state
FROM   dba_db_links  -- 실제로는 v$db_object_cache 또는 세션 뷰 활용
WHERE  type = 'PACKAGE BODY';

-- 세션에서 패키지 상태 확인 (현재 세션 기준)
SELECT sid,
       name,
       type
FROM   v$access
WHERE  sid = SYS_CONTEXT('USERENV', 'SID')
  AND  type = 'PACKAGE';

예방 방법

1. 배포 전략: 서비스 중단 또는 접속 차단 후 DDL 수행

운영 환경에서 패키지나 참조 객체를 변경할 때는 반드시 유지보수 시간(Maintenance Window)을 설정하고, 신규 세션 접속을 차단한 상태에서 DDL 작업을 수행해야 합니다. 배포 완료 후에는 UTL_RECOMP 또는 utlrp.sql을 실행하여 모든 의존 객체가 VALID 상태인지 확인하고, 이후 서비스를 재개하는 절차를 표준화하는 것이 좋습니다. 특히 Connection Pool을 사용하는 환경에서는 Pool의 기존 연결을 완전히 재초기화해야 에러 재발을 막을 수 있습니다.

-- 배포 후 INVALID 객체 없음을 확인하는 검증 쿼리
SELECT COUNT(*) AS invalid_count
FROM   dba_objects
WHERE  status = 'INVALID'
  AND  owner  = 'MY_SCHEMA';
-- 결과가 0이어야 정상 배포 완료

2. 의존성 분석 기반의 순차적 배포 (Dependency-Aware Deployment)

배포 전에 반드시 변경 대상 객체의 의존성을 분석하여, 영향받는 모든 객체를 올바른 순서로 재컴파일하는 배포 스크립트를 작성해야 합니다. Oracle의 DBA_DEPENDENCIES 뷰를 활용하여 의존성 트리를 미리 파악하고, 하위 객체(Referenced Object)부터 상위 객체(Dependent Object) 순서로 배포하면 연쇄적인 INVALID 상태 전파를 최소화할 수 있습니다.

-- 변경 전 영향 범위 사전 분석 쿼리
SELECT LEVEL,
       LPAD(' ', 2*(LEVEL-1)) || object_name AS object_tree,
       object_type,
       status
FROM   (
  SELECT d.name        AS object_name,
         d.type        AS object_type,
         o.status,
         d.referenced_name AS parent_name
  FROM   dba_dependencies d
  JOIN   dba_objects      o
         ON o.object_name = d.name
         AND o.owner      = d.owner
  WHERE  d.owner = 'MY_SCHEMA'
)
START WITH parent_name = 'MY_PACKAGE'  -- 변경 대상 객체명
CONNECT BY PRIOR object_name = parent_name
ORDER SIBLINGS BY object_name;

관련 에러

  • ORA-04062: timestamp of package/procedure/function/trigger has been changed — 참조하는 객체의 타임스탬프가 변경되었을 때 발생하며, ORA-04061과 함께 나타나는 경우가 많습니다.
  • ORA-04065: not executed, altered or dropped stored procedure — 저장 프로시저가 변경되거나 삭제된 경우 발생하며, ORA-04061과 연속으로 출력됩니다.
  • ORA-04068: existing state of packages has been discarded — 패키지의 전체 상태(State)가 폐기된 경우 발생하며, ORA-04061 이후 연속으로 발생하는 대표적인 에러입니다. 이 세 에러는 보통 스택 형태로 함께 출력되므로, 하나를 보면 나머지도 확인해야 합니다.
  • ORA-06508: could not find program unit being called — 호출하려는 프로그램 단위를 찾을 수 없을 때 발생하며, 패키지 INVALID 상태와 밀접하게 연관됩니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기