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

ORA-00069
2026년 05월 31일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-00069 cannot acquire lock – table locks disabled 는?

ORA-00069 에러는 Oracle 데이터베이스에서 특정 테이블에 대한 락(Lock)을 획득하려 할 때, 해당 테이블의 테이블 락(Table Lock, TM Lock)이 비활성화되어 있어 락 획득이 불가능한 경우 발생합니다. 주로 LOCK TABLE 명령이나 DDL 작업(ALTER TABLE, TRUNCATE 등) 또는 DML 작업 시 내부적으로 TM 락이 필요한 상황에서 해당 테이블이 DISABLE TABLE LOCK 상태일 때 이 에러가 발생합니다. Oracle의 병렬 처리(Parallel DML) 성능 향상을 목적으로 특정 테이블의 테이블 락을 의도적으로 비활성화한 경우에도 빈번하게 나타나므로, 운영 환경에서 예상치 못한 장애를 유발할 수 있어 각별한 주의가 필요합니다.


주요 발생 원인

1. 의도적인 DISABLE TABLE LOCK 설정

가장 일반적인 원인으로, DBA 또는 개발자가 병렬 DML 성능 향상이나 특정 상황에서의 락 경합을 줄이기 위해 ALTER TABLE ... DISABLE TABLE LOCK 명령을 실행한 경우입니다. 이 설정이 적용된 상태에서 해당 테이블에 대해 명시적 LOCK TABLE 문이나 DDL 작업을 수행하면 ORA-00069 에러가 즉시 발생합니다.

2. DDL 작업(TRUNCATE, ALTER TABLE 등) 수행 시 내부 TM 락 필요

Oracle은 DDL 작업을 수행할 때 내부적으로 해당 테이블에 대한 TM 락(Exclusive 모드)을 획득해야 합니다. 테이블 락이 비활성화된 상태에서 TRUNCATE TABLE, ALTER TABLE ADD COLUMN, CREATE INDEX 등의 작업을 시도하면 Oracle 엔진이 내부적으로 락 획득에 실패하여 이 에러가 발생합니다. 운영 중 긴급 스키마 변경이 필요할 때 해당 테이블의 락 상태를 사전에 확인하지 않으면 작업이 전혀 진행되지 않습니다.

3. Import/Export(Data Pump) 또는 복제 작업 중 발생

Oracle Data Pump(impdp/expdp), 전통적인 imp/exp 유틸리티, 또는 Oracle Streams/GoldenGate 같은 복제 솔루션은 데이터 일관성을 보장하기 위해 대상 테이블에 대한 락을 획득하려고 시도합니다. 대상 테이블의 테이블 락이 비활성화되어 있으면 이러한 유틸리티들이 ORA-00069 에러와 함께 실패하며, 데이터 이관이나 복제 작업이 중단되는 상황이 발생합니다.


해결 방법

원인 1: 테이블 락 비활성화 상태 확인 및 재활성화

먼저 현재 테이블의 락 상태를 확인한 후, 테이블 락을 다시 활성화합니다.

-- 1단계: 현재 스키마의 테이블 락 상태 전체 확인
SELECT owner,
       table_name,
       table_lock
FROM   dba_tables
WHERE  table_lock = 'DISABLED'
ORDER  BY owner, table_name;

-- 2단계: 특정 테이블의 락 상태 확인
SELECT table_name,
       table_lock
FROM   user_tables
WHERE  table_name = 'YOUR_TABLE_NAME';

-- 3단계: 테이블 락 재활성화
ALTER TABLE your_table_name ENABLE TABLE LOCK;

-- 4단계: 활성화 후 상태 재확인
SELECT table_name,
       table_lock
FROM   user_tables
WHERE  table_name = 'YOUR_TABLE_NAME';

원인 2: DDL 작업 전 테이블 락 상태 확인 및 처리

DDL 작업을 수행하기 전에 항상 락 상태를 점검하고, 필요 시 활성화 후 작업합니다.

-- TRUNCATE 작업 전 처리 예시
-- 1단계: 락 상태 확인
SELECT table_name, table_lock
FROM   user_tables
WHERE  table_name = 'SALES_HISTORY';

-- 2단계: 테이블 락이 DISABLED인 경우 활성화
ALTER TABLE sales_history ENABLE TABLE LOCK;

-- 3단계: DDL 작업 수행
TRUNCATE TABLE sales_history;

-- 4단계: 필요에 따라 다시 DISABLE (권장하지 않음)
-- ALTER TABLE sales_history DISABLE TABLE LOCK;

-- ALTER TABLE 컬럼 추가 작업 예시
ALTER TABLE sales_history ENABLE TABLE LOCK;
ALTER TABLE sales_history ADD (new_column VARCHAR2(100));

원인 3: 테이블 락 상태를 고려한 스크립트 자동화

운영 환경에서 안전하게 사용할 수 있는 자동화 스크립트입니다.

-- 여러 테이블에 대한 일괄 ENABLE 처리 스크립트
BEGIN
   FOR rec IN (
      SELECT owner, table_name
      FROM   dba_tables
      WHERE  table_lock = 'DISABLED'
      AND    owner NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'SYSMAN')
   )
   LOOP
      BEGIN
         EXECUTE IMMEDIATE
            'ALTER TABLE ' || rec.owner || '.' || rec.table_name
            || ' ENABLE TABLE LOCK';
         DBMS_OUTPUT.PUT_LINE(
            'Enabled: ' || rec.owner || '.' || rec.table_name
         );
      EXCEPTION
         WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE(
               'Failed: ' || rec.owner || '.' || rec.table_name
               || ' - ' || SQLERRM
            );
      END;
   END LOOP;
END;
/
-- 명시적 LOCK TABLE 시 에러 재현 및 확인 방법
-- (테스트 환경에서만 수행)

-- 테스트 테이블 생성
CREATE TABLE test_lock_tbl (
   id     NUMBER,
   name   VARCHAR2(50)
);

-- 테이블 락 비활성화
ALTER TABLE test_lock_tbl DISABLE TABLE LOCK;

-- LOCK TABLE 시도 -> ORA-00069 발생
LOCK TABLE test_lock_tbl IN EXCLUSIVE MODE;
-- ORA-00069: cannot acquire lock - table locks disabled for TEST_LOCK_TBL

-- 해결: 테이블 락 활성화
ALTER TABLE test_lock_tbl ENABLE TABLE LOCK;

-- 다시 LOCK TABLE 시도 -> 성공
LOCK TABLE test_lock_tbl IN EXCLUSIVE MODE;
COMMIT;

-- 테스트 테이블 정리
DROP TABLE test_lock_tbl PURGE;
-- Data Pump import 전 사전 점검 쿼리
-- impdp 실패 원인 확인 시 활용
SELECT t.owner,
       t.table_name,
       t.table_lock,
       t.num_rows,
       t.last_analyzed
FROM   dba_tables t
WHERE  t.owner = 'TARGET_SCHEMA'
AND    t.table_lock = 'DISABLED'
ORDER  BY t.table_name;

예방 방법

1. 테이블 락 비활성화 정책 표준화 및 변경 관리 적용

운영 환경에서는 DISABLE TABLE LOCK 명령을 최대한 사용하지 않도록 DBA 운영 가이드라인에 명문화하고, 반드시 사용해야 하는 경우에는 변경 관리(Change Management) 절차를 통해 승인을 받도록 합니다. 또한 정기적인 점검 스크립트를 통해 테이블 락이 비활성화된 객체를 주기적으로 모니터링하고, 이상 발견 시 즉시 담당자에게 알림이 가도록 Oracle Enterprise Manager(OEM) 또는 사용자 정의 Job을 활용합니다.

-- 정기 점검을 위한 DBMS_SCHEDULER 등록 예시
BEGIN
   DBMS_SCHEDULER.CREATE_JOB(
      job_name        => 'CHK_DISABLED_TABLE_LOCK',
      job_type        => 'PLSQL_BLOCK',
      job_action      => '
         DECLARE
            v_count NUMBER;
         BEGIN
            SELECT COUNT(*)
            INTO   v_count
            FROM   dba_tables
            WHERE  table_lock = ''DISABLED''
            AND    owner NOT IN (''SYS'',''SYSTEM'');

            IF v_count > 0 THEN
               -- 알림 로직 또는 로그 테이블 INSERT
               INSERT INTO dba_monitor_log
                  (check_date, check_item, check_value)
               VALUES
                  (SYSDATE, ''DISABLED_TABLE_LOCK_COUNT'', v_count);
               COMMIT;
            END IF;
         END;',
      start_date      => SYSTIMESTAMP,
      repeat_interval => 'FREQ=DAILY; BYHOUR=9; BYMINUTE=0',
      enabled         => TRUE,
      comments        => 'DISABLED TABLE LOCK 정기 점검 JOB'
   );
END;
/

2. DDL 및 데이터 이관 작업 전 사전 체크리스트 의무화

TRUNCATE, ALTER TABLE, Data Pump import 등 DDL 및 이관 작업을 수행하기 전에 반드시 대상 테이블의 table_lock 컬럼 값을 dba_tables 또는 user_tables 뷰에서 확인하는 사전 체크리스트를 팀 표준 절차로 정착시킵니다. 이를 쉘 스크립트나 SQL 스크립트로 자동화하여 작업 시작 전 자동으로 확인 리포트를 생성하도록 구성하면, 실수로 인한 운영 장애를 효과적으로 예방할 수 있습니다.


관련 에러

  • ORA-00054: resource busy and acquire with NOWAIT specified – 테이블 락이 활성화된 상태에서 다른 세션이 이미 락을 보유하고 있을 때 NOWAIT 옵션으로 락 획득을 시도할 경우 발생합니다. ORA-00069와 달리 락 자체는 가능하지만 현재 경합 중인 상태입니다.
  • ORA-00055: maximum number of DML locks exceeded – DML 락의 수가 시스템 파라미터 DML_LOCKS에 설정된 최대값을 초과했을 때 발생하며, DML_LOCKS=0으로 설정하면 사실상 모든 테이블에 대해 TM 락이 비활성화되어 ORA-00069와 유사한 증상이 광범위하게 나타날 수 있습니다.
  • ORA-00060: deadlock detected while waiting for resource – 두 세션이 서로의 락을 대기하는 교착상태(Deadlock) 시 발생하며, 테이블 락과 행 수준 락(Row Lock)이 복합적으로 관련된 경우 ORA-00069 이후 락 재활성화 과정에서 간접적으로 연관될 수 있습니다.
  • ORA-02049: timeout: distributed transaction waiting for lock – 분산 트랜잭션 환경에서 원격 테이블에 대한 락 대기 시간이 초과될 때 발생하며, 원격 테이블의 락이 비활성화된 경우 ORA-00069로 이어질 수 있습니다.
DBMS 에러 코드 시리즈

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

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

댓글 남기기