2026년 09월 07일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-12150 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-12150 TNS: unable to send data 는?
ORA-12150 에러는 Oracle Net(TNS) 레이어에서 데이터를 원격 서버로 전송하는 과정 중 네트워크 통신 실패가 발생했을 때 나타나는 오류입니다. 클라이언트와 데이터베이스 서버 간의 소켓 연결이 수립된 이후에도 실제 데이터 패킷을 전송하는 단계에서 문제가 생길 경우 이 에러가 발생하며, 단순한 연결 실패(ORA-12541)와는 달리 연결 자체는 성립되었으나 데이터 송신 중 끊기는 상황을 의미합니다. 주로 네트워크 불안정, 방화벽 세션 타임아웃, 잘못된 TNS 설정 등 다양한 원인에 의해 트리거되며, 운영 환경에서 갑작스럽게 발생하면 애플리케이션 서비스 중단으로 이어질 수 있어 빠른 진단과 조치가 매우 중요합니다.
주요 발생 원인
1. 네트워크 불안정 및 중간 장비(방화벽/로드밸런서) 세션 타임아웃
가장 빈번하게 발생하는 원인으로, 클라이언트와 DB 서버 사이에 위치한 방화벽이나 로드밸런서가 일정 시간 동안 트래픽이 없는 유휴 연결을 강제로 끊어버리는 경우입니다. Oracle 세션이 장시간 쿼리를 실행하거나 idle 상태로 유지될 때, 중간 장비가 해당 TCP 세션을 종료하면서 다음 데이터 전송 시도 시 ORA-12150이 발생하게 됩니다. 특히 클라우드 환경(AWS, Azure, OCI)에서는 기본 idle 타임아웃이 짧게 설정되어 있어 더욱 자주 발생합니다.
2. sqlnet.ora 또는 tnsnames.ora의 잘못된 설정
sqlnet.ora 파일 내 SQLNET.EXPIRE_TIME, SQLNET.SEND_TIMEOUT, SQLNET.RECV_TIMEOUT 등의 파라미터가 잘못 설정되어 있거나, tnsnames.ora의 HOST, PORT 정보가 실제 서버 환경과 불일치할 때 발생합니다. 특히 클라이언트 측 sqlnet.ora에 극단적으로 짧은 타임아웃 값이 설정된 경우, 대용량 데이터 전송 중 에러가 발생할 수 있으며 이는 애플리케이션 전체에 영향을 미칩니다.
3. 운영체제 수준의 TCP 버퍼 크기 부족 또는 커널 파라미터 문제
Oracle 서버 또는 클라이언트 OS의 TCP 소켓 버퍼 크기(tcp_rmem, tcp_wmem)가 너무 작게 설정되어 있거나, OS 커널의 네트워크 관련 파라미터가 고부하 환경에 맞지 않을 경우 데이터 전송 도중 오류가 발생합니다. 대량 데이터 배치 작업이나 동시 세션이 폭발적으로 늘어나는 상황에서 이 문제가 두드러지게 나타나며, DBA와 시스템 관리자의 협업이 필요한 영역입니다.
해결 방법
원인 1 해결: Dead Connection Detection(DCD) 및 Keep-Alive 설정
sqlnet.ora에 SQLNET.EXPIRE_TIME을 설정하여 Oracle이 주기적으로 연결 생존 여부를 확인하도록 합니다. 이 값은 분 단위이며, 방화벽 타임아웃보다 짧게 설정해야 합니다.
-- sqlnet.ora 파일에 아래 설정 추가 (Oracle Net 설정 파일)
-- 파일 위치: $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.EXPIRE_TIME = 10 -- 10분마다 연결 확인 패킷 전송
-- 현재 세션의 네트워크 관련 파라미터 확인
SELECT name, value
FROM v$parameter
WHERE name IN ('local_listener', 'remote_listener', 'dispatchers')
ORDER BY name;
-- 리스너 상태 및 현재 연결된 세션 수 확인
SELECT s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.last_call_et AS idle_seconds
FROM v$session s
WHERE s.type = 'USER'
AND s.status = 'INACTIVE'
AND s.last_call_et > 600 -- 10분 이상 idle 세션 조회
ORDER BY s.last_call_et DESC;
OS 레벨에서 TCP Keep-Alive도 함께 설정합니다(Linux 기준):
-- OS 레벨 TCP Keep-Alive 확인 (DBA가 시스템 관리자와 협력하여 적용)
-- /etc/sysctl.conf 에 아래 값 설정 권장
-- net.ipv4.tcp_keepalive_time = 300
-- net.ipv4.tcp_keepalive_intvl = 60
-- net.ipv4.tcp_keepalive_probes = 5
-- Oracle 세션에서 현재 네트워크 서비스 설정 조회
SELECT * FROM v$network_service_banner;
원인 2 해결: sqlnet.ora 파라미터 최적화
-- sqlnet.ora 권장 설정 예시
-- $ORACLE_HOME/network/admin/sqlnet.ora
-- SQLNET.SEND_TIMEOUT = 60 (데이터 전송 타임아웃: 초 단위)
-- SQLNET.RECV_TIMEOUT = 60 (데이터 수신 타임아웃: 초 단위)
-- SQLNET.EXPIRE_TIME = 10 (DCD 주기: 분 단위)
-- TCP.CONNECT_TIMEOUT = 15 (연결 타임아웃: 초 단위)
-- DISABLE_OOB = ON (Out-of-Band Break 비활성화, 일부 환경 필요)
-- tnsnames.ora 설정 검증: TNS Ping 테스트 결과를 쿼리로 확인
-- 접속 테스트를 위한 간단한 쿼리
SELECT SYSDATE,
SYS_CONTEXT('USERENV', 'DB_NAME') AS db_name,
SYS_CONTEXT('USERENV', 'SERVER_HOST') AS server_host,
SYS_CONTEXT('USERENV', 'IP_ADDRESS') AS client_ip,
SYS_CONTEXT('USERENV', 'SESSION_USER') AS session_user
FROM DUAL;
-- 현재 세션의 TNS 서비스 명 확인
SELECT s.sid,
s.serial#,
s.service_name,
s.machine,
s.osuser,
n.name AS network_service
FROM v$session s
JOIN v$services n ON s.service_name = n.name
WHERE s.audsid = SYS_CONTEXT('USERENV', 'SESSIONID');
원인 3 해결: OS TCP 버퍼 및 Oracle SDU/TDU 크기 조정
-- tnsnames.ora에서 SDU(Session Data Unit) 크기 조정 예시
-- 대용량 데이터 전송 시 SDU 크기를 늘려 성능 개선 가능
--
-- MYDB =
-- (DESCRIPTION =
-- (SDU = 65535)
-- (ADDRESS = (PROTOCOL = TCP)(HOST = db-server)(PORT = 1521))
-- (CONNECT_DATA =
-- (SERVER = DEDICATED)
-- (SERVICE_NAME = mydb)
-- )
-- )
-- listener.ora에서도 동일하게 SDU 설정
-- LISTENER =
-- (DESCRIPTION_LIST =
-- (DESCRIPTION =
-- (SDU = 65535)
-- (ADDRESS = (PROTOCOL = TCP)(HOST = db-server)(PORT = 1521))
-- )
-- )
-- 현재 세션의 데이터 전송 관련 통계 확인
SELECT sn.name,
ss.value
FROM v$statname sn
JOIN v$sesstat ss ON sn.statistic# = ss.statistic#
JOIN v$session s ON ss.sid = s.sid
WHERE s.audsid = SYS_CONTEXT('USERENV', 'SESSIONID')
AND sn.name IN (
'bytes sent via SQL*Net to client',
'bytes received via SQL*Net from client',
'SQL*Net roundtrips to/from client'
);
-- 네트워크 관련 Wait Event 모니터링 (Top Network Waits)
SELECT event,
total_waits,
total_timeouts,
time_waited,
average_wait
FROM v$system_event
WHERE event LIKE '%SQL*Net%'
OR event LIKE '%TCP%'
ORDER BY time_waited DESC
FETCH FIRST 10 ROWS ONLY;
예방 방법
1. Oracle Net 타임아웃 및 DCD 파라미터 표준화
모든 운영 서버의 sqlnet.ora에 SQLNET.EXPIRE_TIME을 반드시 설정하고, 방화벽 idle 타임아웃 정책과 연동하여 Oracle 쪽 타임아웃이 항상 더 짧게 유지되도록 표준화합니다. 신규 서버 구축 시 체크리스트에 해당 항목을 포함시켜 누락 없이 적용하는 것이 Best Practice이며, 변경 이력을 형상 관리 시스템(Git 등)으로 관리하면 변경에 따른 장애를 빠르게 추적할 수 있습니다.
2. 네트워크 Wait Event 정기 모니터링 및 알림 설정
v$system_event 및 v$session_wait 뷰를 활용한 SQL*Net 관련 Wait Event를 정기적으로 모니터링하고, 임계값 초과 시 자동 알림이 발생하도록 Oracle Enterprise Manager(OEM) 또는 별도 모니터링 툴(Grafana + Prometheus 등)을 구성합니다. 주간 단위로 AWR(Automatic Workload Repository) 리포트의 Top Network Events 섹션을 검토하여 추세 변화를 조기에 파악하는 습관을 갖는 것이 중요합니다.
관련 에러
- ORA-12535: TNS operation timed out — 연결 시도 자체가 타임아웃된 경우로, ORA-12150과 함께 자주 발생합니다.
- ORA-12541: TNS no listener — 리스너가 응답하지 않는 경우이며, 초기 연결 단계에서 발생하는 점이 ORA-12150과 다릅니다.
- ORA-03113: end-of-file on communication channel — 서버 프로세스가 비정상 종료되어 소켓이 끊어진 경우로, ORA-12150 이후 연쇄적으로 발생하기도 합니다.
- ORA-03114: not connected to ORACLE — ORA-12150으로 연결이 끊긴 후 추가 SQL 실행 시 나타나는 후속 에러입니다.
- ORA-12537: TNS connection closed — 원격 측에서 명시적으로 연결을 종료한 경우이며, 방화벽에 의한 강제 종료와 유사한 증상을 보입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.