2026년 06월 27일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-01012 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-01012 not logged on 는?
ORA-01012 에러는 Oracle 데이터베이스 세션이 정상적으로 연결되지 않은 상태에서 SQL 명령이나 데이터베이스 작업을 시도할 때 발생하는 오류입니다. 쉽게 말해, 데이터베이스에 로그인되지 않은 상태이거나 세션이 이미 종료된 상태에서 작업을 계속 진행하려 할 때 Oracle이 이를 감지하고 발생시키는 에러입니다. 특히 애플리케이션 서버와 데이터베이스 사이의 커넥션 풀 환경, 장시간 유휴 세션, 또는 네트워크 단절 이후 재사용된 커넥션에서 자주 목격됩니다.
주요 발생 원인
1. 커넥션 풀에서 이미 종료된(Dead) 커넥션 재사용
애플리케이션 서버(WAS)에서 관리하는 커넥션 풀 내의 커넥션이 Oracle 서버 측에서 이미 끊어졌음에도 불구하고, WAS는 해당 커넥션이 유효하다고 판단하여 재사용하는 경우가 발생합니다. 이는 sqlnet.ora의 SQLNET.EXPIRE_TIME 설정이나 방화벽의 세션 타임아웃으로 인해 서버 측 세션이 강제 종료된 후에도 클라이언트 측이 이를 인지하지 못하는 전형적인 시나리오입니다. 특히 야간 배치 이후 아침 첫 트랜잭션, 또는 장시간 피크 타임 후 트래픽이 급감했다가 다시 올라올 때 빈번하게 발생합니다.
2. 세션 강제 종료(ALTER SYSTEM KILL SESSION) 후 계속 사용
DBA가 ALTER SYSTEM KILL SESSION 또는 ALTER SYSTEM DISCONNECT SESSION 명령으로 특정 세션을 강제 종료했음에도 불구하고, 해당 세션과 연결된 애플리케이션이 이 사실을 인지하지 못하고 계속해서 해당 커넥션으로 SQL을 실행하려 하는 경우입니다. Oracle은 이미 KILL 처리된 세션에 대한 추가 요청을 ORA-01012로 거부합니다. 이는 운영 중 긴급 세션 정리 작업 후 해당 세션의 사용자가 재로그인 없이 작업을 이어가려 할 때 나타납니다.
3. OCI/JDBC 프로그램의 잘못된 커넥션 관리
Oracle Call Interface(OCI)나 JDBC를 직접 사용하는 애플리케이션에서 logoff 또는 connection.close()를 명시적으로 호출한 후에도 해당 커넥션 객체를 계속 사용하거나, 예외 처리 로직의 결함으로 인해 이미 닫힌 커넥션을 다시 사용하는 경우입니다. 특히 멀티스레드 환경에서 커넥션 객체가 여러 스레드 간에 공유될 때, 한 스레드가 커넥션을 닫은 후 다른 스레드가 동일 객체로 SQL을 실행하려 할 때 이 에러가 발생합니다. 코드 리뷰 시 try-finally 블록에서의 커넥션 반납 로직을 반드시 점검해야 합니다.
해결 방법
원인 1: 죽은 커넥션(Dead Connection) 탐지 및 제거
현재 데이터베이스 세션 상태를 조회하여 비정상 세션을 확인합니다.
-- 현재 세션 상태 전체 조회 (KILLED 또는 SNIPED 상태 확인)
SELECT sid,
serial#,
username,
status,
last_call_et,
machine,
program,
sql_id
FROM v$session
WHERE status IN ('KILLED', 'SNIPED')
ORDER BY last_call_et DESC;
-- 장시간 유휴 세션 조회 (1시간 이상 아무 작업 없는 세션)
SELECT sid,
serial#,
username,
status,
ROUND(last_call_et / 3600, 2) AS idle_hours,
machine,
program
FROM v$session
WHERE last_call_et > 3600
AND username IS NOT NULL
ORDER BY last_call_et DESC;
-- 특정 세션 강제 종료
ALTER SYSTEM KILL SESSION '&sid,&serial#' IMMEDIATE;
커넥션 풀 수준에서의 유효성 검사 쿼리를 설정하는 것도 중요합니다.
-- 커넥션 풀 Validation Query 용도로 사용 (항상 성공하는 쿼리)
SELECT 1 FROM DUAL;
-- 또는 Oracle 전용 ping 용도
SELECT SYSDATE FROM DUAL;
원인 2: KILL SESSION 이후 처리 확인
DBA가 세션을 종료한 후 해당 세션이 완전히 정리되었는지 확인하는 방법입니다.
-- KILL 처리 이후 세션이 완전히 사라졌는지 확인
SELECT sid,
serial#,
username,
status,
last_call_et
FROM v$session
WHERE sid = &killed_sid;
-- 결과가 없으면 완전히 종료된 것, KILLED 상태면 아직 롤백 중
-- OS 프로세스 레벨에서 강제 종료 (DISCONNECT 옵션 사용)
ALTER SYSTEM DISCONNECT SESSION '&sid,&serial#' POST_TRANSACTION;
-- 즉시 강제 종료
ALTER SYSTEM DISCONNECT SESSION '&sid,&serial#' IMMEDIATE;
원인 3: 애플리케이션 커넥션 객체 상태 진단
애플리케이션 레벨에서 커넥션 상태를 확인하고 재연결하는 패턴입니다.
-- 특정 프로그램/머신에서 열린 커넥션 수 확인
SELECT machine,
program,
status,
COUNT(*) AS session_count
FROM v$session
WHERE username = '&APP_USER'
GROUP BY machine, program, status
ORDER BY session_count DESC;
-- 애플리케이션 사용자의 최근 SQL 실행 이력 확인
SELECT s.sid,
s.serial#,
s.username,
s.status,
q.sql_text,
q.last_active_time
FROM v$session s
JOIN v$sql q ON s.sql_id = q.sql_id
WHERE s.username = '&APP_USER'
ORDER BY q.last_active_time DESC;
sqlnet.ora 설정을 통한 Dead Connection 조기 감지
-- sqlnet.ora 파일에 아래 파라미터 추가 (단위: 분)
-- SQLNET.EXPIRE_TIME = 10
-- 이 설정은 SQL*Net 레벨에서 10분마다 커넥션 유효성을 체크합니다.
-- 현재 설정값 확인 (alert log 또는 파라미터 뷰 활용)
SHOW PARAMETER sqlnet;
-- 프로파일을 통한 유휴 세션 자동 종료 설정
CREATE PROFILE app_user_profile LIMIT
IDLE_TIME 30 -- 30분 유휴 시 세션 SNIPED 처리
CONNECT_TIME 480; -- 최대 8시간 연결 허용
-- 프로파일 사용자에게 적용
ALTER USER app_schema PROFILE app_user_profile;
-- 적용 확인
SELECT username, profile
FROM dba_users
WHERE username = 'APP_SCHEMA';
예방 방법
1. 커넥션 풀 Validation(유효성 검사) 설정 강화
운영 환경의 커넥션 풀(HikariCP, DBCP2, UCP 등)에서는 반드시 testOnBorrow, validationQuery, keepAlive 옵션을 활성화해야 합니다. 커넥션을 풀에서 꺼낼 때마다 SELECT 1 FROM DUAL과 같은 경량 쿼리로 유효성을 확인하면 Dead Connection을 사전에 제거할 수 있습니다. Oracle Universal Connection Pool(UCP)을 사용한다면 setValidateConnectionOnBorrow(true) 설정과 함께 setConnectionLabelingCallback을 활용하여 보다 정교한 커넥션 상태 관리가 가능합니다. 또한 SQLNET.EXPIRE_TIME을 sqlnet.ora에 설정하여 네트워크 레벨의 Dead Connection을 서버 측에서 능동적으로 감지하도록 구성하는 것을 권장합니다.
2. 애플리케이션 코드의 예외 처리 및 재연결 로직 표준화
모든 데이터베이스 접근 코드에서 ORA-01012를 포함한 커넥션 관련 예외(ORA-03113, ORA-03114 등) 발생 시 해당 커넥션을 즉시 폐기(evict)하고 풀에서 새로운 커넥션을 획득하는 표준 재시도(Retry) 로직을 구현해야 합니다. Java의 경우 SQLException의 getSQLState()와 getErrorCode()를 활용하여 커넥션 레벨 에러를 정확히 구분하고, Spring의 @Retryable 어노테이션이나 커스텀 DataSourceHealthIndicator를 통해 자동 복구 메커니즘을 구축하는 것이 Best Practice입니다. 주기적인 커넥션 풀 상태 모니터링 대시보드 구축도 병행하여 비정상 커넥션이 누적되는 상황을 실시간으로 감지할 수 있도록 해야 합니다.
관련 에러
- ORA-03113:
end-of-file on communication channel— 네트워크 단절 또는 서버 프로세스 비정상 종료 시 발생하며, ORA-01012와 함께 나타나는 경우가 많습니다. - ORA-03114:
not connected to ORACLE— ORA-01012와 유사하게 연결이 끊어진 상태에서의 작업 시도 시 발생합니다. - ORA-02396:
exceeded maximum idle time, please connect again— 프로파일의IDLE_TIME초과 시 발생하며, 이후 재접속 없이 작업 시 ORA-01012로 이어질 수 있습니다. - ORA-00028:
your session has been killed— DBA에 의해 세션이 KILL된 직후 해당 세션에서 발생하며, 이어지는 작업에서 ORA-01012가 뒤따릅니다. - ORA-01041:
internal error. hostdef extension doesn't exist— OCI 레벨에서 커넥션 상태가 불일치할 때 발생하며 ORA-01012와 원인이 유사합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.