접속 장애 전환
CTF, TAF, FAN의 차이와 인스턴스 장애 시 서비스 전환 실습, 조회 복구와 미커밋 작업의 한계
#핵심 요약
CTF는 접속 생성 단계에서 실패한 주소 대신 다른 주소로 재시도하는 기능임
TAF는 이미 연결된 세션의 인스턴스 장애 뒤 재연결과 설정된 범위의 조회 복구임
FAN은 상태 변화의 알림이며 실제 연결 처리와 요청 재시도는 클라이언트 기능에 달려 있음
세션이 넘어갔는지는 GV$SESSION의 FAILOVER_TYPE, FAILOVER_METHOD, FAILED_OVER로 확인함
#개념과 동작 원리
| 설정, 기능 | 담당 범위 |
|---|---|
| LOAD_BALANCE | 주소 선택과 분산 |
| FAILOVER | 접속 실패 시 다른 주소로 재시도 |
| FAILOVER_MODE | 연결된 세션의 TAF 방식 지정 |
| TAF SESSION | 세션 재연결이며 진행 중 SELECT의 결과 수신 재개는 제공하지 않음 |
| TAF SELECT | 재연결 후 조회를 재실행해 이미 받은 행을 제외한 Fetch 복구 가능 |
| BASIC | 장애 후 대체 연결 생성 |
| PRECONNECT | 장애 전에 백업 연결을 확보하므로 추가 연결 자원 필요 |
| FAN, ONS | 노드, 인스턴스, 서비스의 UP/DOWN 상태 이벤트 전달 |
| FCF | FAN을 사용하는 연결 풀의 장애 연결 정리와 관리 |
| 구분 | 적용 시점 |
|---|---|
| CTF | 세션 생성 전 최초 접속 단계 |
| TAF | 이미 연결된 세션의 인스턴스 장애 이후 |
TAF SELECT는 지원 클라이언트와 설정, 조회 복구 조건이 충족돼야 하며 기존 인스턴스 메모리와 세션 전체를 복사하는 기능은 아님
FAILOVER의 기본값은 ON이므로 tnsnames.ora에서 생략했다고 CTF가 꺼졌다고 판단하지 않음
실습 과제에는 FAILOVER = on을 지운 뒤 접속을 비교하는 항목이 있었음
노드 장애 때 VIP가 다른 노드로 옮겨 가거나 접속 실패를 빨리 돌려줘, 긴 TCP timeout 대기 없이 다음 주소로 넘어가게 도와줌
FAN은 SQL 실행 실패나 TCP timeout으로 장애를 알아차리는 지연을 줄이고, ONS가 Clusterware와 DB의 이벤트를 지원 클라이언트와 미들웨어에 전달함
| 구분 | TAF | FCF |
|---|---|---|
| 적용 대상 | 개별 세션 | 연결 풀 전체 |
| 감지 | 수업 자료는 TCP timeout 뒤 감지로 정리 | ONS 이벤트 |
| 중간 계층 | 제한적 | UCP, JDBC, ODP.NET |
수업 자료의 "TAF는 TCP timeout 뒤 감지"는 모든 지원 클라이언트의 감지 동작을 단정하는 기준으로 쓰지 않음
서비스의 -failovertype은 SESSION, SELECT가 TAF, TRANSACTION이 Application Continuity(AC), AUTO가 Transparent Application Continuity(TAC)에 해당함
#PDB 서비스의 장애 전환
PDB 연결 서비스를 한 인스턴스에 Preferred, 다른 인스턴스에 Available로 두면, 인스턴스 장애 때 Clusterware가 Available 인스턴스에서 서비스를 기동하고 연결된 PDB를 열어 접속을 받음
수업 자료의 흐름: 인스턴스 장애 감지 → Available 인스턴스의 서비스 기동과 PDB OPEN → FAN 상태 통지 → TAF 세션 재연결
실제 DOWN/UP 이벤트와 클라이언트 반응 시점은 구성과 장애 상황에 따라 달라짐
서비스 속성으로 TAF 정책을 두면 클라이언트마다 같은 FAILOVER_MODE를 반복해 적지 않아도 됨
#필수 명령어 또는 SQL
#클라이언트 TAF 별칭
<TAF_ALIAS> =
(DESCRIPTION =
(ADDRESS_LIST =
(LOAD_BALANCE = on)
(FAILOVER = on)
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_1>)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_2>)(PORT = 1521)))
(CONNECT_DATA =
(SERVICE_NAME = <SERVICE_NAME>)
(FAILOVER_MODE = (TYPE = SELECT)(METHOD = BASIC))))
<NO_TAF_ALIAS> =
(DESCRIPTION =
(ADDRESS_LIST =
(LOAD_BALANCE = on)
(FAILOVER = on)
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_1>)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_2>)(PORT = 1521)))
(CONNECT_DATA = (SERVICE_NAME = <SERVICE_NAME>)))결과 해석:
실습 기록:
- CTF: 접속하는 인스턴스가 번갈아 나오는 것을 본 뒤
<INSTANCE1>을SHUTDOWN IMMEDIATE로 내리고 새로 접속하자<INSTANCE2>로 붙었음 - TAF 없는 별칭:
<INSTANCE1>에 붙은 세션은<INSTANCE1>을SHUTDOWN ABORT한 뒤 다음 조회에서ORA-03113: end-of-file on communication channel로 끊겼고, 다시 접속해야<INSTANCE2>로 붙었음 TYPE=SELECT:emp를INSERT INTO emp SELECT * FROM emp반복으로 수만 건으로 늘리고 조회 결과를 받는 도중<INSTANCE1>을SHUTDOWN ABORT하자, 조회가 잠시 멈췄다가<INSTANCE2>로 넘어가 이어졌음
#PRECONNECT와 백업 연결
<PRIMARY_ALIAS> =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_1>)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = <SERVICE_NAME>)
(INSTANCE_NAME = <INSTANCE1>)
(FAILOVER_MODE =
(BACKUP = <BACKUP_ALIAS>)
(TYPE = SELECT)(METHOD = PRECONNECT)
(RETRIES = 30)(DELAY = 5))))
<BACKUP_ALIAS> =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = <VIP_2>)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = <SERVICE_NAME>)(INSTANCE_NAME = <INSTANCE2>)))SELECT inst_id, sid, username, failover_type, failover_method, failed_over
FROM gv$session
WHERE username = '<USERNAME>';결과 해석:
BACKUP이 없으면 미리 만들 백업 연결의 대상을 정할 수 없고, LOAD_BALANCE = on이면 주 연결이 1번 인스턴스로 고정되지 않을 수 있어 실습에서는 주 별칭과 백업 별칭을 인스턴스별로 따로 뒀음
실습 기록: PRECONNECT 별칭으로 접속하자 2번 노드의 서버 프로세스가 22개에서 23개로 늘어 백업 연결이 미리 잡힌 것을 확인했음
확인 기준은 inst_id 1과 2에 같은 사용자 세션이 있고 FAILOVER_METHOD = PRECONNECT인 것, <INSTANCE1> SHUTDOWN ABORT 뒤 inst_id 2 세션의 FAILED_OVER = YES임
서버측 TAF의 srvctl -failovermethod는 NONE, BASIC만 받으며 PRECONNECT는 클라이언트 tnsnames.ora에서만 지정함
#서비스 속성으로 서버측 TAF
srvctl add service -db <DB_NAME> -service <SERVICE_NAME> \
-preferred <INSTANCE1> -available <INSTANCE2> \
-failovertype SELECT -failovermethod BASIC \
-failoverretry 30 -failoverdelay 5 -notification TRUE
srvctl start service -db <DB_NAME> -service <SERVICE_NAME>
srvctl config service -db <DB_NAME> -service <SERVICE_NAME> | grep -i -E 'failover|notification'
srvctl status service -db <DB_NAME> -service <SERVICE_NAME>결과 해석:
기본 서비스(DB 이름과 같은 서비스)는 srvctl로 바꿀 수 없어 업무용 서비스를 따로 만듦
클라이언트 별칭은 SERVICE_NAME만 적고 FAILOVER_MODE를 생략함
서비스의 TAF 속성이 클라이언트 FAILOVER_MODE보다 우선한다고 수업 자료는 정리함
확인 기준: GV$SESSION에서 FAILOVER_TYPE = SELECT, FAILOVER_METHOD = BASIC, 장애 뒤 FAILED_OVER = YES, srvctl status service에서 서비스가 <INSTANCE2>로 옮겨 감
#PDB 서비스 장애 전환 실습
srvctl modify service -db <DB_NAME> -service <SERVICE_NAME> \
-failovertype SELECT -failovermethod BASIC \
-failoverretry 30 -failoverdelay 5 -notification TRUE
srvctl config scan
lsnrctl services | grep -i <SERVICE_NAME>
# 조회 결과를 한 화면씩 넘기는 도중 다른 노드에서
srvctl stop instance -db <DB_NAME> -instance <INSTANCE1> -stopoption abort
srvctl status service -db <DB_NAME> -service <SERVICE_NAME>
# 확인 뒤 원래대로
srvctl start instance -db <DB_NAME> -instance <INSTANCE1>
srvctl relocate service -db <DB_NAME> -service <SERVICE_NAME> -oldinst <INSTANCE2> -newinst <INSTANCE1>SELECT inst_id, open_mode FROM gv$pdbs WHERE name = '<PDB_NAME>';
SELECT inst_id, username, service_name, failover_type, failover_method, failed_over
FROM gv$session
WHERE username = '<USERNAME>';결과 해석:
리스너에 등록된 실제 서비스 이름에 도메인이 붙었는지 lsnrctl services로 먼저 확인하고, tnsnames.ora 별칭은 SCAN 주소와 그 서비스 이름으로 1번 노드, 2번 노드 모두에 둠
실습 기록: 접속 세션은 SYS_CONTEXT('userenv', 'instance_name')이 <INSTANCE1>이었고, SET PAUSE ON으로 dba_objects를 넘기는 도중 <INSTANCE1>을 abort하자 서비스가 <INSTANCE2>로 옮겨 갔으며 Enter로 조회가 이어진 뒤 <INSTANCE2>, FAILED_OVER = YES로 나왔음
#FAN, FCF용 서비스와 ONS 점검
srvctl add service -db <DB_NAME> -service <SERVICE_NAME> \
-preferred <INSTANCE1>,<INSTANCE2> \
-failovertype AUTO -failovermethod BASIC \
-failoverretry 180 -failoverdelay 5 \
-commit_outcome TRUE -replay_init_time 600 -notification TRUE
srvctl status ons
srvctl config ons
crsctl status resource -tSELECT name, aq_ha_notifications, failover_method, failover_type,
failover_retries, failover_delay, clb_goal
FROM dba_services
WHERE LOWER(name) = '<SERVICE_NAME>';결과 해석:
-commit_outcome TRUE는 커밋 결과를 추적해 중복 커밋을 막고, -replay_init_time 600은 장애 뒤 600초 안의 재실행을 허용한다고 수업 자료는 설명함
수업 자료에는 DBMS_SERVICE.MODIFY_SERVICE로 aq_ha_notifications => TRUE와 FAILOVER_TYPE_SESSION, FAILOVER_TYPE_SELECT를 바꾸는 예도 있음
"TRANSACTION"이라는 주석과 실제 값 FAILOVER_TYPE_SELECT가 맞지 않고, Clusterware가 관리하는 서비스는 srvctl 정의가 기준이라 DBMS_SERVICE 변경이 재기동 때 덮어써질 수 있음
19c 클라이언트는 SCAN 주소 하나만 적어도 SCAN 이름이 가리키는 여러 IP로 분산된다고 수업 자료는 설명함
#확인 문제: 노드 점검 때 TAF 조회 세션이 넘어가는지 미리 확인
상황: 2번 노드 서버 점검으로 <INSTANCE2>를 강제로 내려야 하고, 조회 사용자들은 TAF 별칭으로 접속해 있음
다시 로그인하지 않고 계속 조회되는지, 실제로 넘어간 세션인지 숫자로 보이고 점검 뒤 <INSTANCE2>를 다시 올려야 함
실습에서는 TAF 별칭으로 접속을 반복해 <INSTANCE2>에 붙은 세션을 하나 만들고 emp를 조회한 채 창을 열어 둠
SELECT inst_id, username, failover_type, failover_method, failed_over
FROM gv$session
WHERE username = '<SCHEMA>';srvctl stop instance -db <DB_NAME> -instance <INSTANCE2> -stopoption abort
srvctl status database -db <DB_NAME>SELECT instance_name FROM v$instance;
SELECT empno, ename, sal FROM emp WHERE deptno = 20;srvctl start instance -db <DB_NAME> -instance <INSTANCE2>
srvctl status database -db <DB_NAME>결과 해석:
예상값: 장애 전 INST_ID 2, SELECT, BASIC, NO, 장애 뒤 같은 조회가 다시 로그인 없이 되고 INST_ID 1, FAILED_OVER = YES
-stopoption abort는 SHUTDOWN ABORT에 해당함
FAILED_OVER = YES 세션과 장애 뒤 새로 접속한 세션(NO)을 구분함
TYPE=SELECT는 조회만 이어 주며, 장애 순간의 미커밋 DML은 롤백되어 애플리케이션이 다시 실행해야 함
실행 결과 확인 불가
#사용 조건과 주의사항
조회 Fetch 복구와 미커밋 UPDATE 복구는 다르며 TAF는 미커밋 DML을 자동 재실행하지 않음
인스턴스 장애 복구는 미커밋 트랜잭션을 롤백하며, 재실행은 AC, TAC의 영역임
SQL*Plus 세션 하나가 다른 인스턴스로 다시 붙은 결과만으로 연결 풀의 FCF 동작을 입증할 수 없음
notification 설정만으로 모든 클라이언트의 자동 복구가 보장되지 않음
SHUTDOWN ABORT, srvctl stop instance -stopoption abort는 해당 인스턴스의 모든 세션을 끊으므로 운영 환경에서 시험하지 않음