2026년 09월 06일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-12048 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-12048 error encountered while refreshing materialized view 는?
ORA-12048 에러는 Materialized View(구체화된 뷰)를 갱신(Refresh)하는 과정에서 내부적으로 오류가 발생했을 때 Oracle 데이터베이스가 반환하는 에러입니다. 이 에러는 단독으로 발생하기보다는 실제 원인을 설명하는 하위 에러(예: ORA-01555, ORA-04021, ORA-00942 등)와 함께 에러 스택 형태로 나타나는 경우가 대부분입니다. 주로 자동 또는 수동 Refresh 작업 중에 기반 테이블(Base Table)의 변경, 권한 문제, 네트워크 단절, 언두(Undo) 공간 부족 등 다양한 원인으로 인해 발생할 수 있습니다.
주요 발생 원인
- 기반 테이블(Base Table) 또는 뷰에 대한 권한 부족 혹은 객체 미존재
Materialized View를 소유한 스키마가 기반 테이블에 대한 SELECT 권한을 잃었거나, 기반 테이블 혹은 DB Link가 삭제·변경된 경우 Refresh 시 ORA-12048이 발생합니다. 특히 DB Link를 통한 원격 Materialized View 환경에서는 원격 객체의 구조 변경(컬럼 추가/삭제, 테이블 재생성 등)이 빈번하게 이 문제를 유발합니다.
- 언두(Undo) 세그먼트 부족 또는 스냅샷 너무 오래됨 (ORA-01555: Snapshot Too Old)
Complete Refresh 또는 Fast Refresh 중에 Undo 공간이 충분하지 않거나, Undo Retention 시간이 너무 짧게 설정되어 Refresh 도중 읽어야 할 이전 버전의 데이터 블록이 이미 덮어쓰여진 경우 ORA-01555와 함께 ORA-12048이 발생합니다. 대용량 테이블을 기반으로 하는 Materialized View일수록 Undo 공간 관리가 매우 중요합니다.
- Materialized View Log 손상 또는 Fast Refresh 조건 불충족
Fast Refresh 방식을 사용할 때 Materialized View Log가 삭제·손상되었거나, 기반 테이블에 DDL 변경이 발생하여 로그가 무효화된 경우 Refresh가 실패하며 ORA-12048이 발생합니다. 또한 Materialized View 정의 쿼리가 Fast Refresh의 제약 조건(집계 함수 미지원, 조인 조건 불충족 등)을 만족하지 못하는 경우에도 동일한 문제가 나타날 수 있습니다.
해결 방법
원인 1: 권한 부족 및 객체 미존재 해결
먼저 에러 스택을 확인하여 정확한 객체명과 에러를 파악한 뒤, 누락된 권한을 부여하거나 DB Link 상태를 점검합니다.
-- Materialized View 소유자에게 기반 테이블 권한 부여
GRANT SELECT ON schema_name.base_table TO mv_owner;
-- DB Link 유효성 확인
SELECT * FROM dba_db_links WHERE owner = 'MV_OWNER';
-- DB Link를 통한 원격 테이블 접근 테스트
SELECT COUNT(*) FROM remote_table@your_db_link;
-- Materialized View 상태 확인
SELECT mview_name, staleness, compile_state, last_refresh_date
FROM dba_mviews
WHERE mview_name = 'YOUR_MV_NAME';
-- Materialized View 재컴파일 (객체 재생성 후 필요 시)
BEGIN
DBMS_MVIEW.REFRESH(
list => 'SCHEMA_NAME.MV_NAME',
method => 'C', -- Complete Refresh
atomic_refresh => FALSE
);
END;
/
원인 2: Undo 공간 부족 해결
Undo Retention을 늘리거나 Undo Tablespace를 확장하고, Refresh를 부하가 적은 시간대에 실행합니다.
-- 현재 Undo Retention 설정 확인
SHOW PARAMETER UNDO_RETENTION;
-- Undo Retention 값 증가 (단위: 초, 예시: 3600초 = 1시간)
ALTER SYSTEM SET UNDO_RETENTION = 3600 SCOPE = BOTH;
-- Undo Tablespace 크기 확인
SELECT tablespace_name, file_name, bytes/1024/1024 AS size_mb
FROM dba_data_files
WHERE tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace');
-- Undo Tablespace 데이터 파일 확장
ALTER DATABASE DATAFILE '/u01/oradata/undo01.dbf' RESIZE 4096M;
-- Undo 사용량 실시간 모니터링
SELECT used_ublks, used_urec, status
FROM v$transaction;
-- Materialized View Refresh를 atomic_refresh=FALSE로 실행하여 Undo 사용 최소화
BEGIN
DBMS_MVIEW.REFRESH(
list => 'SCHEMA_NAME.MV_NAME',
method => 'C',
atomic_refresh => FALSE -- 대용량 MV에서 Undo 사용 절감
);
END;
/
원인 3: Materialized View Log 손상 및 Fast Refresh 불가 해결
Materialized View Log를 재생성하거나 Fast Refresh 대신 Complete Refresh로 전환합니다.
-- Materialized View Log 상태 확인
SELECT log_owner, master, log_table, log_trigger, rowids, primary_key, sequence
FROM dba_mview_logs
WHERE master = 'BASE_TABLE_NAME';
-- 손상된 Materialized View Log 삭제 후 재생성
DROP MATERIALIZED VIEW LOG ON schema_name.base_table;
CREATE MATERIALIZED VIEW LOG ON schema_name.base_table
WITH ROWID, SEQUENCE (col1, col2, col3)
INCLUDING NEW VALUES;
-- Fast Refresh 가능 여부 사전 점검
DECLARE
v_msg VARCHAR2(4000);
BEGIN
DBMS_MVIEW.EXPLAIN_MVIEW(
mv => 'SELECT col1, col2 FROM schema_name.base_table',
msg_array => v_msg
);
DBMS_OUTPUT.PUT_LINE(v_msg);
END;
/
-- Fast Refresh 불가 시 Complete Refresh로 강제 전환
BEGIN
DBMS_MVIEW.REFRESH(
list => 'SCHEMA_NAME.MV_NAME',
method => 'C', -- 'C': Complete, 'F': Fast, '?': Force
atomic_refresh => FALSE
);
END;
/
-- Refresh 실패 이력 조회 (alert log 보조 확인용)
SELECT mview_name, last_refresh_date, staleness, compile_state
FROM dba_mviews
WHERE compile_state != 'VALID';
예방 방법
- 정기적인 Materialized View 상태 모니터링 자동화
DBA_MVIEWS, DBA_MVIEW_LOGS 뷰를 주기적으로 조회하는 모니터링 스크립트를 작성하여 DBMS_SCHEDULER 또는 크론(Cron) 잡으로 매일 실행하고, COMPILE_STATE가 ‘VALID’가 아니거나 STALENESS가 ‘NEEDS_COMPILE’인 경우 즉시 담당자에게 알림이 가도록 설정합니다. 또한 Refresh 실패 시 자동으로 Complete Refresh를 재시도하는 예외 처리 로직을 Refresh 프로시저에 포함시키는 것이 좋습니다.
“`sql
— 매일 오전 2시 Materialized View 상태 점검 스케줄러 등록 예시
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => ‘CHECK_MV_STATUS’,
job_type => ‘PLSQL_BLOCK’,
job_action => ‘
DECLARE
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count
FROM dba_mviews
WHERE compile_state != ”VALID”
OR staleness IN (”NEEDS_COMPILE”, ”UNUSABLE”);
IF v_count > 0 THEN
— 알림 발송 또는 로그 기록
INSERT INTO mv_alert_log (check_time, issue_count)
VALUES (SYSDATE, v_count);
COMMIT;
END IF;
END;’,
start_date => SYSTIMESTAMP,
repeat_interval => ‘FREQ=DAILY;BYHOUR=2;BYMINUTE=0’,
enabled => TRUE
);
END;
/
“`
- Undo Tablespace 충분한 크기 유지 및 Guaranteed Retention 설정
대용량 Materialized View Refresh가 예상되는 환경에서는 Undo Tablespace를 Autoextend로 설정하고, RETENTION GUARANTEE 옵션을 활성화하여 Refresh 도중 Undo 데이터가 강제로 덮어쓰이는 상황을 방지합니다. Undo Retention은 가장 오래 걸리는 Refresh 작업 시간보다 최소 20~30% 이상 여유 있게 설정하는 것이 실무에서 권장됩니다.
“`sql
— Undo Tablespace에 Retention Guarantee 설정
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;
— Autoextend 활성화
ALTER DATABASE DATAFILE ‘/u01/oradata/undotbs01.dbf’
AUTOEXTEND ON NEXT 512M MAXSIZE 20480M;
“`
관련 에러
- ORA-01555 (Snapshot Too Old): Undo 세그먼트가 부족하여 Refresh 중 일관된 읽기가 불가능할 때 ORA-12048과 함께 발생합니다.
- ORA-00942 (Table or View Does Not Exist): 기반 테이블이나 DB Link 객체가 삭제되거나 권한이 없을 때 함께 발생합니다.
- ORA-04021 (Timeout Waiting to Lock Object): Refresh 중 기반 테이블에 Lock이 걸려 대기 시간이 초과될 때 나타납니다.
- ORA-12008 (Error in Materialized View Refresh Path): ORA-12048의 상위 개념으로, Refresh 경로 전반의 오류를 포괄합니다.
- ORA-23421 (Job Number Is Not a Job in the Job Queue): DBMS_JOB 기반 자동 Refresh 스케줄 설정 오류와 연관될 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.