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

ORA-00031
2026년 05월 29일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-00031 session marked for kill 는?

ORA-00031 에러는 Oracle DBA가 특정 세션을 강제 종료하기 위해 ALTER SYSTEM KILL SESSION 명령을 실행했을 때, 해당 세션이 즉시 종료되지 않고 “kill 대기 상태”로 표시될 때 발생합니다. 이 에러는 엄밀히 말하면 에러라기보다는 상태 메시지에 가까우며, 대상 세션이 현재 롤백 작업, 네트워크 대기, 또는 OS 레벨의 작업을 수행 중이어서 즉시 종료할 수 없는 상황임을 의미합니다. DBA 입장에서는 세션이 완전히 사라질 때까지 기다리거나, 더 강력한 방법(OS 레벨 kill)을 사용해야 하는 경우가 대부분입니다.


주요 발생 원인

1. 대용량 트랜잭션의 롤백 진행 중

가장 흔한 원인으로, 대량의 DML(INSERT, UPDATE, DELETE) 작업 도중 세션을 kill하면 Oracle은 데이터 일관성을 위해 반드시 롤백을 완료해야 합니다. 롤백 작업이 진행되는 동안 세션은 “marked for kill” 상태로 남아 있으며, 롤백이 완전히 끝나야만 세션이 실제로 종료됩니다. 대용량 트랜잭션일수록 롤백 시간이 길어져 이 상태가 오래 지속될 수 있습니다.

2. 네트워크 단절 또는 응답 없는 클라이언트

클라이언트 측의 네트워크 연결이 비정상적으로 끊어졌거나, 클라이언트 프로세스가 응답하지 않는 상태일 때 Oracle 서버는 해당 세션에 kill 신호를 보내도 즉각적인 응답을 받지 못합니다. 이 경우 세션은 Oracle 내부적으로 종료 대기 상태로 표시되지만, 실제 OS 프로세스는 여전히 살아있어 장시간 유지될 수 있습니다. 특히 방화벽이나 로드밸런서 환경에서 자주 발생하는 패턴입니다.

3. OS 리소스 대기 또는 I/O 블로킹

세션이 OS 레벨에서 디스크 I/O, 메모리 스왑, 또는 기타 시스템 리소스를 기다리고 있는 경우, Oracle 프로세스가 kill 신호를 처리할 수 없는 상태가 됩니다. 이런 상황에서는 Oracle 자체적으로 세션을 종료하는 것이 불가능하며, OS 레벨에서 직접 프로세스를 종료해야 합니다. 스토리지 장애나 과부하 상황에서 특히 자주 발생합니다.


해결 방법

Step 1. 현재 “marked for kill” 세션 확인

-- kill 대기 중인 세션 목록 조회
SELECT sid,
       serial#,
       username,
       status,
       osuser,
       machine,
       program,
       sql_id,
       last_call_et AS seconds_since_last_call
FROM   v$session
WHERE  status = 'KILLED'
ORDER  BY last_call_et DESC;

Step 2. 해당 세션의 OS 프로세스 ID(SPID) 확인

-- Oracle SID와 OS 프로세스 ID 매핑 조회
SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       p.spid        AS os_process_id,
       s.machine,
       s.program
FROM   v$session s
JOIN   v$process p ON s.paddr = p.addr
WHERE  s.status = 'KILLED';

Step 3. IMMEDIATE 옵션으로 재시도

-- 일반적인 kill 명령 (비동기 방식)
ALTER SYSTEM KILL SESSION '123,456';

-- IMMEDIATE 옵션 사용 (즉시 종료 시도 - 권장)
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;

> 주의: IMMEDIATE 옵션은 롤백 없이 즉시 종료를 시도하므로, 진행 중이던 트랜잭션은 백그라운드에서 롤백됩니다.

Step 4. OS 레벨에서 프로세스 강제 종료 (최후 수단)

-- SPID 확인 후 OS에서 kill (Linux/Unix 환경)
-- 아래 쿼리로 spid 확인
SELECT p.spid
FROM   v$session s
JOIN   v$process p ON s.paddr = p.addr
WHERE  s.sid = 123
AND    s.serial# = 456;
# Linux/Unix OS 레벨에서 강제 종료
kill -9 <spid>

# 예시
kill -9 28475

Step 5. 롤백 진행 상황 모니터링

-- 롤백 진행률 확인 (undo 사용량 기반)
SELECT s.sid,
       s.serial#,
       s.username,
       t.used_ublk          AS undo_blocks_used,
       t.used_urec          AS undo_records_used,
       ROUND(t.used_ublk * 8192 / 1024 / 1024, 2) AS undo_mb
FROM   v$session s
JOIN   v$transaction t ON s.taddr = t.addr
WHERE  s.status = 'KILLED';
-- 전체 롤백 세그먼트 활동 확인
SELECT usn,
       state,
       undoblks,
       xacts,
       rssize / 1024 / 1024 AS undo_size_mb
FROM   v$rollstat
WHERE  xacts > 0;

예방 방법

1. IDLE_TIME 프로파일 설정으로 좀비 세션 자동 정리

장시간 유휴 상태인 세션이 누적되면 관리 부담이 증가하고, 갑작스러운 kill 상황이 빈번해집니다. Oracle 프로파일의 IDLE_TIME 파라미터를 설정하면 일정 시간 이상 아무 작업도 하지 않는 세션을 자동으로 종료할 수 있습니다.

-- 유휴 세션 자동 종료 프로파일 생성 (30분 기준)
CREATE PROFILE idle_session_profile LIMIT
    IDLE_TIME          30
    SESSIONS_PER_USER  10
    CONNECT_TIME       480;

-- 특정 사용자에게 프로파일 적용
ALTER USER app_user PROFILE idle_session_profile;

-- 프로파일 적용 여부 확인
SELECT username, profile
FROM   dba_users
WHERE  username = 'APP_USER';

2. 대량 DML 작업 시 배치(Batch) 처리 및 중간 커밋 전략 도입

대용량 트랜잭션은 롤백 시 막대한 시간이 소요되므로, 처음부터 작업을 분할하여 중간 커밋을 수행하는 설계가 필요합니다. 이를 통해 만약 세션 kill이 필요한 상황에서도 롤백 범위가 최소화되어 ORA-00031 상태가 오래 지속되는 것을 방지할 수 있습니다.

-- 나쁜 예: 한 번에 대량 삭제 (롤백 부담 큼)
DELETE FROM large_table WHERE status = 'EXPIRED';
COMMIT;

-- 좋은 예: 배치 단위로 나누어 처리
DECLARE
    v_rows_deleted NUMBER := 0;
BEGIN
    LOOP
        DELETE FROM large_table
        WHERE  status = 'EXPIRED'
        AND    ROWNUM <= 10000;

        v_rows_deleted := SQL%ROWCOUNT;
        COMMIT;

        EXIT WHEN v_rows_deleted < 10000;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('Delete completed.');
END;
/

관련 에러

  • ORA-00030: no such session – 존재하지 않는 SID/Serial# 조합으로 kill을 시도할 때 발생합니다.
  • ORA-00028: your session has been killed – kill된 세션의 사용자 측에서 수신하는 에러로, 세션이 성공적으로 종료되었음을 의미합니다.
  • ORA-01013: user requested cancel of current operation – 사용자가 직접 작업을 취소했을 때 발생하며, kill 과정에서도 간접적으로 연관될 수 있습니다.
  • ORA-00600: 내부 오류로, 비정상적인 세션 종료 과정에서 드물게 연관되어 발생할 수 있습니다.

> 30년 DBA 경험에서 드리는 한 마디: ORA-00031 상태의 세션을 발견했을 때 조급하게 OS kill을 남발하지 마세요. 롤백이 진행 중이라면 기다리는 것이 가장 안전합니다. OS kill을 무분별하게 사용하면 데이터 블록 손상이나 undo 세그먼트 문제로 이어질 수 있으니, 반드시 v$transaction으로 롤백 진행 상황을 확인한 후 결정하시기 바랍니다.


DBMS 에러 코드 시리즈

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

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

댓글 남기기