2026년 05월 28일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-00019 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-00019 maximum number of session licenses exceeded 는?
ORA-00019 에러는 Oracle 데이터베이스에 허가된 최대 세션(라이선스) 수를 초과했을 때 발생하는 에러입니다. Oracle은 라이선스 정책에 따라 동시 접속 가능한 세션 수를 제한할 수 있으며, 이 한계치를 넘어서는 새로운 접속 요청이 들어올 경우 해당 에러와 함께 접속이 거부됩니다. 운영 환경에서 갑작스럽게 발생하면 신규 사용자 접속이 전면 차단되므로, DBA가 즉각적으로 대응해야 하는 Critical 에러 중 하나입니다.
주요 발생 원인
1. LICENSE_MAX_SESSIONS 파라미터 설정값 초과
Oracle 데이터베이스에는 LICENSE_MAX_SESSIONS라는 초기화 파라미터가 존재하며, 이 값이 0보다 큰 숫자로 설정되어 있을 경우 해당 숫자만큼만 동시 세션을 허용합니다. 이 파라미터가 실제 업무량에 비해 낮게 설정되어 있거나, 과거 소규모 환경 기준으로 설정된 값이 그대로 유지된 채 사용자가 증가했을 때 가장 빈번하게 발생합니다.
2. 세션 누수(Session Leak)로 인한 좀비 세션 누적
애플리케이션 코드에서 DB 커넥션을 제대로 반환(close)하지 않거나, 커넥션 풀 설정이 잘못되어 있는 경우 세션이 정상적으로 종료되지 않고 지속적으로 누적됩니다. 이렇게 쌓인 비활성(INACTIVE) 세션들이 라이선스 카운트를 계속 점유하면서, 실제 유효한 세션이 들어올 자리가 없어지는 상황을 만들어냅니다.
3. 배치 작업 또는 이벤트성 트래픽으로 인한 순간적 접속 폭증
정기적인 배치 프로그램이 다수의 병렬 세션을 동시에 생성하거나, 이벤트성 서비스(프로모션, 대규모 업데이트 등)로 인해 순간적으로 접속자가 폭증할 경우 평소에는 문제없던 세션 한계치를 초과할 수 있습니다. 이 경우는 평상시에 에러가 없다가 특정 시간대나 이벤트 직후에만 에러가 발생하는 패턴을 보이므로 원인 파악이 다소 늦어지는 경향이 있습니다.
해결 방법
원인 1: LICENSE_MAX_SESSIONS 파라미터 조정
먼저 현재 설정값과 실제 세션 현황을 확인합니다.
-- 현재 라이선스 관련 파라미터 확인
SELECT NAME, VALUE, DESCRIPTION
FROM V$PARAMETER
WHERE NAME IN ('license_max_sessions', 'license_max_users', 'license_sessions_warning');
-- 현재 활성 세션 수 확인
SELECT COUNT(*) AS TOTAL_SESSIONS,
STATUS,
TYPE
FROM V$SESSION
GROUP BY STATUS, TYPE
ORDER BY STATUS;
-- 전체 세션 수 한눈에 보기
SELECT COUNT(*) AS CURRENT_SESSION_COUNT
FROM V$SESSION
WHERE TYPE = 'USER';
값을 확인한 후, 파라미터를 즉시 변경합니다. LICENSE_MAX_SESSIONS는 동적 파라미터이므로 재시작 없이 적용 가능합니다.
-- 동적으로 즉시 변경 (재시작 불필요)
ALTER SYSTEM SET LICENSE_MAX_SESSIONS = 500 SCOPE = BOTH;
-- 변경 확인
SELECT NAME, VALUE
FROM V$PARAMETER
WHERE NAME = 'license_max_sessions';
-- 경고 임계치도 함께 조정 (최대값의 80% 수준 권장)
ALTER SYSTEM SET LICENSE_SESSIONS_WARNING = 400 SCOPE = BOTH;
> ⚠️ 주의: LICENSE_MAX_SESSIONS 값을 0으로 설정하면 제한이 해제됩니다. 단, Oracle 라이선스 계약 범위 내에서 설정해야 법적 문제가 없습니다.
원인 2: 좀비 세션(비활성 세션) 정리
오래된 비활성 세션을 식별하고 강제 종료합니다.
-- 비활성 세션 중 장시간 방치된 세션 조회 (30분 이상 INACTIVE)
SELECT S.SID,
S.SERIAL#,
S.USERNAME,
S.STATUS,
S.MACHINE,
S.PROGRAM,
S.LOGON_TIME,
ROUND((SYSDATE - S.LAST_CALL_ET / 86400) * 1440, 0) AS INACTIVE_MINUTES,
S.LAST_CALL_ET AS INACTIVE_SECONDS
FROM V$SESSION S
WHERE S.STATUS = 'INACTIVE'
AND S.TYPE = 'USER'
AND S.LAST_CALL_ET > 1800 -- 1800초 = 30분
ORDER BY S.LAST_CALL_ET DESC;
-- 특정 세션 강제 종료 (SID와 SERIAL# 확인 후 실행)
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;
-- 다수의 좀비 세션을 일괄 종료하는 스크립트 생성
SELECT 'ALTER SYSTEM KILL SESSION ''' || SID || ',' || SERIAL# || ''' IMMEDIATE;'
FROM V$SESSION
WHERE STATUS = 'INACTIVE'
AND TYPE = 'USER'
AND LAST_CALL_ET > 3600 -- 1시간 이상 비활성
AND USERNAME IS NOT NULL;
위 쿼리로 생성된 KILL 구문을 검토 후 실행하면 됩니다. 운영 환경에서는 반드시 해당 세션의 업무 영향도를 먼저 확인하고 종료해야 합니다.
원인 3: 순간적 접속 폭증 대응
접속 폭증 시점을 분석하고 커넥션 풀 설정을 최적화합니다.
-- 시간대별 세션 생성 추이 확인 (AWR 기반)
SELECT TO_CHAR(SAMPLE_TIME, 'YYYY-MM-DD HH24') AS HOUR_SLOT,
COUNT(*) AS SESSION_SAMPLES
FROM DBA_HIST_ACTIVE_SESS_HISTORY
WHERE SAMPLE_TIME >= SYSDATE - 1
GROUP BY TO_CHAR(SAMPLE_TIME, 'YYYY-MM-DD HH24')
ORDER BY HOUR_SLOT;
-- 현재 접속 중인 프로그램/머신별 세션 분포 확인
SELECT MACHINE,
PROGRAM,
USERNAME,
STATUS,
COUNT(*) AS SESSION_COUNT
FROM V$SESSION
WHERE TYPE = 'USER'
GROUP BY MACHINE, PROGRAM, USERNAME, STATUS
ORDER BY SESSION_COUNT DESC;
-- 특정 IP 또는 프로그램의 세션 수 제한 (Profile 활용)
-- 프로파일 생성: 단일 사용자의 동시 세션 수 제한
CREATE PROFILE LIMITED_SESSION_PROFILE LIMIT
SESSIONS_PER_USER 10
IDLE_TIME 30
CONNECT_TIME 480;
-- 특정 사용자에게 프로파일 적용
ALTER USER app_user PROFILE LIMITED_SESSION_PROFILE;
-- 적용 확인
SELECT USERNAME, PROFILE
FROM DBA_USERS
WHERE USERNAME = 'APP_USER';
예방 방법
1. 세션 모니터링 자동화 및 임계치 알람 설정
LICENSE_SESSIONS_WARNING 파라미터를 최대 세션 수의 70~80% 수준으로 설정해두면, 한계에 도달하기 전 Oracle Alert Log에 경고 메시지가 기록됩니다. 여기에 더해 아래와 같은 모니터링 쿼리를 Cron 또는 OEM(Oracle Enterprise Manager) 스크립트로 주기적으로 실행하고, 임계치 초과 시 담당자에게 알람을 발송하는 체계를 구축하는 것이 좋습니다.
-- 세션 사용률 모니터링 쿼리 (배치/모니터링 스크립트에 활용)
SELECT (SELECT VALUE FROM V$PARAMETER WHERE NAME = 'license_max_sessions') AS MAX_SESSIONS,
(SELECT COUNT(*) FROM V$SESSION WHERE TYPE = 'USER') AS CURRENT_SESSIONS,
ROUND(
(SELECT COUNT(*) FROM V$SESSION WHERE TYPE = 'USER') /
NULLIF((SELECT TO_NUMBER(VALUE) FROM V$PARAMETER WHERE NAME = 'license_max_sessions'), 0)
* 100, 2
) AS USAGE_PCT
FROM DUAL;
사용률이 80%를 넘으면 즉시 알람이 울리도록 구성해두면, 실제 장애로 이어지기 전에 선제적으로 대응할 수 있습니다.
2. 애플리케이션 레벨 커넥션 풀 관리 정책 수립
세션 누수의 근본 원인은 대부분 애플리케이션 코드에 있습니다. 개발 표준에 DB 커넥션 반드시 명시적 close 처리를 의무화하고, WAS(WebLogic, JBoss 등) 커넥션 풀의 Minimum/Maximum Pool Size, Inactive Connection Timeout, Test on Borrow 옵션을 적절히 설정해야 합니다. 정기적으로(월 1회 이상) 아래 쿼리로 장기 비활성 세션 현황을 점검하는 루틴을 DBA 업무 프로세스에 포함시키는 것을 강력히 권장합니다.
-- 월간 세션 누수 점검 쿼리
SELECT USERNAME,
MACHINE,
PROGRAM,
COUNT(*) AS INACTIVE_COUNT,
MAX(LAST_CALL_ET) AS MAX_INACTIVE_SEC,
MIN(LOGON_TIME) AS OLDEST_LOGON
FROM V$SESSION
WHERE STATUS = 'INACTIVE'
AND TYPE = 'USER'
AND LAST_CALL_ET > 600 -- 10분 이상 비활성
GROUP BY USERNAME, MACHINE, PROGRAM
HAVING COUNT(*) >= 3
ORDER BY INACTIVE_COUNT DESC;
관련 에러
- ORA-00018:
maximum number of sessions exceeded—SESSIONS파라미터 초과로 발생. ORA-00019가 라이선스 기반 제한이라면, ORA-00018은 DB 내부 구성 파라미터(SESSIONS) 기반의 제한입니다. 둘 다 동시에 점검해야 할 경우가 많습니다. - ORA-00020:
maximum number of processes exceeded—PROCESSES파라미터 초과. 세션 수와 프로세스 수는 밀접하게 연관되어 있으며, ORA-00019 해소 후 ORA-00020이 연달아 발생하는 케이스도 있으므로PROCESSES파라미터도 함께 검토해야 합니다. - ORA-02391:
exceeded simultaneous SESSIONS_PER_USER limit— 특정 사용자 Profile에 설정된 동시 세션 수 초과 시 발생. 사용자 단위 세션 제한이 필요한 경우 ORA-00019 대신 이 에러를 유도하는 방식으로 세분화 관리가 가능합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.