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

ORA-00055
2026년 10월 23일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-00055 maximum number of DML locks exceeded 는?

ORA-00055 에러는 Oracle 데이터베이스에서 DML(Data Manipulation Language) 락(Lock)의 최대 허용 개수를 초과했을 때 발생하는 에러입니다. Oracle은 INSERT, UPDATE, DELETE, MERGE 등의 DML 작업이 수행될 때 해당 테이블에 대해 내부적으로 DML 락을 설정하며, 이 락의 총 개수가 초기화 파라미터 DML_LOCKS에서 정의한 한도를 넘어서면 이 에러가 발생합니다. 특히 동시에 많은 트랜잭션이 수행되는 OLTP 환경이나 대규모 배치 작업이 동시에 실행되는 상황에서 빈번하게 발생할 수 있으며, 즉각적인 조치를 취하지 않으면 애플리케이션 전체가 DML 작업을 수행하지 못하는 심각한 장애로 이어질 수 있습니다.


주요 발생 원인

  • DML_LOCKS 파라미터 값이 너무 낮게 설정된 경우

Oracle의 DML_LOCKS 파라미터는 데이터베이스 전체에서 동시에 허용할 수 있는 DML 락의 최대 개수를 결정합니다. 기본값은 4 * TRANSACTIONS 파라미터 값으로 자동 계산되지만, 시스템 부하가 증가하거나 동시 접속 세션이 급격히 늘어난 경우에는 이 기본값이 턱없이 부족할 수 있습니다. 특히 시스템 초기 구성 시 충분한 여유값 없이 설정된 경우, 운영 환경이 확장되면서 이 에러가 반복적으로 발생하게 됩니다.

  • 커밋 또는 롤백 없이 장시간 트랜잭션이 유지되는 경우

DML 락은 트랜잭션이 커밋(COMMIT)이나 롤백(ROLLBACK)으로 종료될 때까지 계속 유지됩니다. 애플리케이션에서 트랜잭션을 적절히 종료하지 않고 장시간 열어 두면, 해당 세션이 보유한 DML 락이 누적되어 전체 시스템의 락 가용량을 고갈시키는 원인이 됩니다. 이는 잘못된 애플리케이션 설계나 오류 처리 로직의 부재로 인해 COMMIT/ROLLBACK이 실행되지 않는 상황에서 자주 발생합니다.

  • 과도한 동시 세션 및 대량 DML 배치 작업의 동시 실행

수백 개의 세션이 동시에 여러 테이블에 DML을 수행하거나, 야간 배치 작업과 주간 OLTP 작업이 겹치는 경우 DML 락 소비량이 급격히 증가합니다. 하나의 트랜잭션이 여러 테이블에 동시에 DML을 수행하면 각 테이블마다 별도의 DML 락이 필요하기 때문에, 복잡한 트랜잭션이 많을수록 락 소비가 기하급수적으로 늘어납니다. 적절한 작업 스케줄링 없이 배치와 온라인 트랜잭션이 동시에 실행되는 환경에서 이 에러가 특히 자주 발생합니다.


해결 방법

1. 현재 DML_LOCKS 파라미터 값 및 사용 현황 확인

먼저 현재 설정값과 실제 사용량을 파악하는 것이 우선입니다.

-- 현재 DML_LOCKS 파라미터 값 확인
SHOW PARAMETER DML_LOCKS;

-- 또는 V$PARAMETER 뷰를 통해 확인
SELECT name, value, description
FROM v$parameter
WHERE name = 'dml_locks';

-- 현재 활성 DML 락 사용 현황 확인
SELECT COUNT(*) AS current_dml_locks
FROM v$lock
WHERE type = 'TM';

-- 세션별 DML 락 보유 현황 상세 조회
SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       s.program,
       l.type,
       l.lmode,
       l.request,
       o.object_name,
       o.object_type
FROM v$session s
JOIN v$lock l ON s.sid = l.sid
JOIN dba_objects o ON l.id1 = o.object_id
WHERE l.type = 'TM'
ORDER BY s.sid;

2. DML_LOCKS 파라미터 값 증가

현재 값이 부족하다고 판단되면 파라미터 값을 증가시킵니다. DML_LOCKS는 동적 파라미터가 아니므로 데이터베이스 재시작이 필요합니다.

-- SPFILE을 사용하는 경우 (권장 방식)
-- 현재 TRANSACTIONS 파라미터 값 먼저 확인
SELECT name, value
FROM v$parameter
WHERE name IN ('transactions', 'dml_locks');

-- DML_LOCKS를 TRANSACTIONS * 6 수준으로 증가 (예시)
ALTER SYSTEM SET DML_LOCKS = 10000 SCOPE = SPFILE;

-- 변경 사항 확인 (재시작 전)
SELECT name, value
FROM v$spparameter
WHERE name = 'dml_locks';

-- 데이터베이스 재시작 후 적용 (운영 환경에서는 계획된 다운타임 활용)
-- SHUTDOWN IMMEDIATE;
-- STARTUP;

> ⚠️ 주의: DML_LOCKS = 0으로 설정하면 DML 락 기능 자체가 비활성화됩니다. 이는 SERIALIZABLE 트랜잭션 격리 수준을 사용할 수 없게 만들고 데드락 탐지가 불가능해지므로, 임시 방편으로도 권장하지 않습니다.

3. 장시간 열린 트랜잭션(미종료 세션) 조회 및 강제 종료

-- 장시간 활성 상태인 트랜잭션 및 세션 조회
SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       s.last_call_et AS elapsed_seconds,
       s.program,
       s.machine,
       t.start_time AS transaction_start,
       t.used_ublk AS undo_blocks_used
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE s.status = 'ACTIVE'
  AND s.last_call_et > 3600  -- 1시간 이상 경과한 세션
ORDER BY s.last_call_et DESC;

-- 문제가 되는 세션 강제 종료 (DBA 권한 필요)
-- SID와 SERIAL# 는 위 조회 결과에서 확인
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;

-- 여러 세션을 한 번에 종료하는 스크립트 생성
SELECT 'ALTER SYSTEM KILL SESSION ''' || sid || ',' || serial# || ''' IMMEDIATE;'
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE s.last_call_et > 7200  -- 2시간 이상 경과
  AND s.username NOT IN ('SYS', 'SYSTEM');

4. 현재 TM 락 점유 상위 세션 분석

-- TM 락을 가장 많이 보유한 세션 TOP 10
SELECT s.sid,
       s.serial#,
       s.username,
       s.program,
       s.machine,
       COUNT(l.id1) AS tm_lock_count,
       LISTAGG(o.object_name, ', ') WITHIN GROUP (ORDER BY o.object_name) AS locked_objects
FROM v$session s
JOIN v$lock l ON s.sid = l.sid AND l.type = 'TM'
JOIN dba_objects o ON l.id1 = o.object_id
GROUP BY s.sid, s.serial#, s.username, s.program, s.machine
ORDER BY tm_lock_count DESC
FETCH FIRST 10 ROWS ONLY;

예방 방법

  • DML_LOCKS 파라미터 적정값 산정 및 모니터링 자동화

운영 환경에서는 DML_LOCKS 값을 TRANSACTIONS 파라미터의 최소 5~6배 수준으로 여유 있게 설정하고, 주기적으로 실제 사용량을 모니터링하는 체계를 갖추는 것이 중요합니다. 아래와 같이 현재 사용률을 정기적으로 체크하는 모니터링 쿼리를 스케줄링하여, 사용률이 80%를 초과하면 DBA에게 알람을 발송하는 체계를 구축하세요.

“`sql

— DML 락 사용률 모니터링 쿼리 (정기 스케줄링 권장)

SELECT p.value AS dml_locks_limit,

COUNT(l.type) AS current_usage,

ROUND(COUNT(l.type) / p.value * 100, 2) AS usage_pct

FROM v$parameter p

CROSS JOIN v$lock l

WHERE p.name = ‘dml_locks’

AND l.type = ‘TM’

GROUP BY p.value;

“`

  • 애플리케이션 레벨의 트랜잭션 관리 원칙 준수

애플리케이션 개발 단계에서부터 트랜잭션을 짧고 명확하게 유지하는 원칙을 반드시 적용해야 합니다. 모든 DML 작업은 성공 시 즉시 COMMIT, 실패 시 ROLLBACK을 수행하도록 예외 처리 로직을 구현하고, 하나의 트랜잭션에서 처리하는 테이블 수를 최소화하도록 설계해야 합니다. 대량 배치 작업은 일정 건수(예: 10,000건)마다 중간 COMMIT을 수행하는 청크(Chunk) 처리 방식을 도입하여 락 보유 시간을 최소화하는 것이 Best Practice입니다.


관련 에러

  • ORA-00060: deadlock detected while waiting for resource — DML 락과 밀접하게 연관된 에러로, 두 세션이 서로의 락을 기다리는 교착 상태 발생 시 나타납니다.
  • ORA-04021: timeout occurred while waiting to lock object — 락 획득 대기 시간 초과 시 발생하며, DML 락 경합 환경에서 함께 나타나는 경우가 많습니다.
  • ORA-00054: resource busy and acquire with NOWAIT specified — NOWAIT 옵션 사용 시 즉시 락을 획득하지 못할 경우 발생하며, DML 락 경합 상황에서 연쇄적으로 발생할 수 있습니다.
  • ORA-02049: timeout: distributed transaction waiting for lock — 분산 트랜잭션 환경에서 락 대기 타임아웃 발생 시 나타나며, DML 락 고갈 상황과 복합적으로 나타날 수 있습니다.
DBMS 에러 코드 시리즈

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

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

댓글 남기기