오라클 데이터베이스의 응급 잠금 해제를 위한 OS 프로세스 관리 전략

고착된 세션의 운영체제 레벨 제거 필요성

데이터베이스 관리 중 특정 세션이 'KILLED' 상태로 표시됨에도 불구하고 시스템 자원을 계속 점유하고 방출하지 않는 경우가 발생합니다. 이 경우 재시작보다는 위험성이 낮은 대안으로, 데이터베이스 내부 명령이 실패할 때 운영체제 (OS) 차원에서 해당 스레드나 프로세스를 직접 단절하는 방법이 적용됩니다.

1. 잠긴 객체 및 세션 식별

어떤 대상물이 현재 자원을 비정상적으로 잡고 있는지 파악하기 위해 데이터 사전 뷰들을 조인하여 조회합니다. 여기서는 ANSI 조인 구문을 사용하여 가독성을 높이고 중복을 줄였습니다.

SELECT o.object_name AS resource_obj,
       m.machine AS client_host,
       sess.sid AS session_id,
       sess.serial# AS session_serial
FROM v$locked_object lock_info
JOIN dba_objects o ON lock_info.object_id = o.object_id
JOIN v$session sess ON lock_info.session_id = sess.sid;

2. 데이터베이스 내부 중단 명령 생성

식별된 세션에 대해 먼저 표준 데이터베이스 단위의 중단 명령을 시도해야 합니다. 이를 수동으로 입력하는 대신, 조회 결과에 기반해 명령문을 자동으로 생성할 수 있는 스크립트를 활용합니다.

SELECT 'ALTER SYSTEM KILL SESSION ''' || sess.sid || ',' || sess.serial# || ''';'
AS termination_command
FROM v$locked_object lock_info
JOIN dba_objects o ON lock_info.object_id = o.object_id
JOIN v$session sess ON lock_info.session_id = sess.sid;

3. 프로세스 주소와 OS 식별자 매핑

위 명령어를 실행 후에도 상태가 변경되지 않고 자원이 유지된다면, 해당 세션이 매핑된 운영체제의 프로세스 (PID) 나 스레드 정보를 확인해야 합니다. 이를 위해 세션 뷰와 프로세스 뷰를 연결합니다.

SELECT proc.spid AS os_pid,
       sess.os_username,
       sess.program AS app_program
FROM v$session sess
JOIN v$process proc ON sess.paddr = proc.addr
WHERE sess.sid = {조회한_SID};

4. 운영체제 레벨 강제 종료 (플랫폼별)

Linux 환경

유닉스 계열 OS 에서 는 관리자 권한 (root) 을 가진 사용자로 로그인한 상태에서 프로세스 종료 신호를 보내야 합니다. 이전에 조회한 `spid` 값을 대체하여 사용합니다.

# example: pid 12345 를 타겟팅
sudo kill -9 12345

Windows 환경

Windows 는 단일 EXE 파일 (ORACLE.EXE) 내부에서 스레드로 동작하므로, 일반적인 작업 관리자 (Task Manager) 로 프로세스를 끝낼 경우 모든 사용자 연결과 백그라운드 서비스에 치명적인 오류를 유발할 수 있습니다. 따라서 Oracle 공급자의 유틸리티인 `orakill` 을 사용해야 합니다.

이 도구는 인스턴스 이름과 타겟 스레드 ID 를 인자로 받습니다. 구체적인 스레드 번호를 찾기 위해서는 Microsoft Resource Kit 의 도구 (예: PStat, Qslice 등) 를 활용할 수 있습니다.

c:\> orakill ORCL 2760
Kill of thread id 2760 in instance ORCL successfully signalled[sic].

관련 SQL 문 추적

특정 프로세스나 세션에서 어떤 SQL 문장이 실행되고 있었는지 역추적해야 할 때가 있습니다. 공유 풀의 SQL 정보와 세션 정보를 결합하여 확인할 수 있습니다.

SELECT q.sql_text
FROM v$sqlarea q
JOIN gv$session ses ON q.sql_id = ses.sql_id
JOIN gv$process p ON ses.paddr = p.addr
WHERE p.program LIKE 'ORACLE.EXE%';

태그: Oracle Database DBA linux Windows

6월 18일 17:44에 게시됨