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

ORA-65049
2026년 10월 14일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-65049 creation of local user, role or profile is not allowed in CDB$ROOT 는?

ORA-65049 에러는 Oracle Multitenant 아키텍처(CDB/PDB 구조)에서 CDB$ROOT 컨테이너에 로컬 사용자(Local User), 로컬 롤(Local Role), 또는 로컬 프로파일(Local Profile)을 생성하려 할 때 발생하는 에러입니다. Oracle 12c 이후 도입된 멀티테넌트 환경에서는 CDB$ROOT는 공통(Common) 오브젝트만 허용하며, 로컬 오브젝트는 반드시 개별 PDB(Pluggable Database) 내에서만 생성해야 합니다. 즉, 기존 Non-CDB 환경에서의 습관대로 CDB$ROOT에서 일반 사용자나 롤을 생성하려 하면 이 에러가 발생하게 됩니다.


주요 발생 원인

1. CDB 환경 인식 없이 CDB$ROOT에서 사용자 생성 시도

가장 흔한 원인으로, DBA가 현재 접속된 컨테이너가 CDB$ROOT임을 인지하지 못하고 일반 사용자를 CREATE USER 구문으로 생성하려 할 때 발생합니다. Oracle 12c 이전 Non-CDB 환경에 익숙한 DBA라면 특히 자주 겪는 상황이며, CDB$ROOT에서는 반드시 CONTAINER=ALL 옵션을 사용하는 공통(Common) 사용자(이름이 C##으로 시작해야 함)만 생성할 수 있습니다.

2. PDB에 접속하지 않고 롤(Role) 또는 프로파일(Profile) 생성 시도

CDB$ROOT에 접속한 상태에서 특정 애플리케이션에만 적용되어야 할 로컬 롤이나 프로파일을 생성할 때 이 에러가 발생합니다. CDB$ROOT에서는 CONTAINER=ALL 구문 없이 생성하는 롤/프로파일은 모두 로컬 오브젝트로 간주되어 에러가 발생하며, 반드시 대상 PDB로 세션을 전환(ALTER SESSION SET CONTAINER)한 후 생성해야 합니다.

3. 스크립트 자동화 또는 마이그레이션 중 컨테이너 전환 누락

Non-CDB에서 CDB 환경으로 데이터베이스를 마이그레이션하거나, 자동화 스크립트로 대량의 사용자/롤/프로파일을 생성할 때 컨테이너 전환 구문이 누락된 경우 발생합니다. 마이그레이션 스크립트가 Non-CDB 환경 기반으로 작성되어 있다면 CDB 환경에서는 그대로 실행할 수 없으며, 컨테이너 인식 로직을 반드시 추가해야 합니다.


해결 방법

해결 방법 1: 현재 컨테이너 확인 후 PDB로 전환하여 로컬 사용자 생성

먼저 현재 어떤 컨테이너에 접속해 있는지 확인합니다.

-- 현재 컨테이너 확인
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') AS current_container FROM DUAL;

-- 모든 PDB 목록 확인
SELECT CON_ID, NAME, OPEN_MODE FROM V$PDBS;

현재 CDB$ROOT에 있다면, 원하는 PDB로 세션을 전환한 후 사용자를 생성합니다.

-- 대상 PDB로 세션 전환
ALTER SESSION SET CONTAINER = ORCLPDB1;

-- PDB 내에서 로컬 사용자 생성 (정상 동작)
CREATE USER app_user IDENTIFIED BY "SecurePass123!"
  DEFAULT TABLESPACE users
  TEMPORARY TABLESPACE temp
  QUOTA UNLIMITED ON users;

-- 권한 부여
GRANT CONNECT, RESOURCE TO app_user;

해결 방법 2: CDB 전체에 공통(Common) 사용자 생성

CDB$ROOT에서 반드시 생성해야 하는 경우라면, 공통 사용자(Common User)로 생성해야 합니다. 공통 사용자의 이름은 반드시 C##으로 시작해야 합니다.

-- CDB$ROOT에서 공통 사용자 생성 (C## 접두어 필수)
CREATE USER C##global_admin IDENTIFIED BY "AdminPass456!"
  CONTAINER = ALL;

-- 공통 롤 부여
GRANT DBA TO C##global_admin CONTAINER = ALL;

-- 공통 롤 생성 방법
CREATE ROLE C##common_role CONTAINER = ALL;
GRANT CREATE SESSION TO C##common_role CONTAINER = ALL;

해결 방법 3: PDB에서 로컬 롤 및 프로파일 생성

-- 대상 PDB로 전환
ALTER SESSION SET CONTAINER = ORCLPDB1;

-- 로컬 롤 생성
CREATE ROLE app_read_role;
GRANT SELECT ANY TABLE TO app_read_role;

-- 로컬 프로파일 생성
CREATE PROFILE app_user_profile LIMIT
  SESSIONS_PER_USER          3
  CPU_PER_SESSION            UNLIMITED
  CPU_PER_CALL               3000
  CONNECT_TIME               30
  IDLE_TIME                  10
  FAILED_LOGIN_ATTEMPTS      5
  PASSWORD_LIFE_TIME         90
  PASSWORD_REUSE_TIME        365
  PASSWORD_LOCK_TIME         1/24;

-- 생성된 프로파일을 사용자에게 적용
ALTER USER app_user PROFILE app_user_profile;

해결 방법 4: 마이그레이션 스크립트에 컨테이너 전환 로직 추가

-- 마이그레이션 스크립트 예시 (PDB 전환 포함)
DECLARE
  v_pdb_name VARCHAR2(30) := 'ORCLPDB1';
BEGIN
  -- 대상 PDB로 전환
  EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER = ' || v_pdb_name;
  
  -- 사용자 생성 (이미 존재하면 무시)
  BEGIN
    EXECUTE IMMEDIATE 
      'CREATE USER migrated_user IDENTIFIED BY "MigPass789!" 
       DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp';
  EXCEPTION
    WHEN OTHERS THEN
      IF SQLCODE = -1920 THEN  -- ORA-01920: user name conflicts
        DBMS_OUTPUT.PUT_LINE('User already exists, skipping...');
      ELSE
        RAISE;
      END IF;
  END;

  EXECUTE IMMEDIATE 'GRANT CONNECT, RESOURCE TO migrated_user';
  DBMS_OUTPUT.PUT_LINE('Migration completed for: ' || v_pdb_name);
END;
/

예방 방법

1. DBA 세션 시작 시 항상 현재 컨테이너를 확인하는 습관화

모든 DDL 작업 전 현재 접속된 컨테이너를 확인하는 것을 DBA 표준 운영 절차(SOP)에 포함시켜야 합니다. SQL*Plus 프롬프트에 컨테이너 이름을 표시하도록 설정하거나, 로그인 트리거를 활용하여 DBA가 현재 위치를 항상 인식할 수 있도록 환경을 구성하는 것이 좋습니다.

-- SQL*Plus 프롬프트에 컨테이너 표시 설정
SET SQLPROMPT "_USER'@'_CONNECT_IDENTIFIER CDB:&&_CONNECT_IDENTIFIER> "

-- 또는 로그인 후 항상 확인하는 별칭 설정 (glogin.sql에 추가)
-- SELECT SYS_CONTEXT('USERENV','CON_NAME') FROM DUAL;

2. CDB/PDB 환경에 맞는 스크립트 템플릿 표준화

팀 내에서 사용하는 사용자/롤/프로파일 생성 스크립트를 CDB 환경에 맞게 표준 템플릿화하여 관리해야 합니다. 모든 스크립트 상단에 컨테이너 확인 및 전환 로직을 포함하고, CI/CD 파이프라인이나 형상관리 시스템에 스크립트 사전 검증(Pre-validation) 단계를 추가하여 CDB$ROOT에서 로컬 오브젝트 생성을 시도하는 구문이 포함된 스크립트가 실행되지 않도록 차단하는 것이 중요합니다.


관련 에러

  • ORA-65048: CDB$ROOT에서 공통 사용자/롤에 허용되지 않는 작업을 수행할 때 발생하는 에러입니다.
  • ORA-65050: Common User나 Role을 생성할 때 이름에 C## 접두어가 없을 경우 발생합니다 (common user or role name must begin with C## 또는 유사 메시지).
  • ORA-01031: 사용자 생성에 필요한 권한이 없을 때 발생하며, CDB 환경에서는 공통 사용자 생성 시 CREATE USER 권한을 CONTAINER=ALL로 부여받아야 합니다.
  • ORA-65040: PDB가 닫혀 있는 상태에서 해당 PDB에 접근하거나 작업을 수행하려 할 때 발생할 수 있으므로, PDB OPEN 여부를 먼저 확인해야 합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기