데이터베이스 연구실.log

서비스와 로드 밸런싱

RAC 서비스의 Preferred와 Available 배치, PDB 서비스와 Scheduler 작업 및 접속 부하 분산

RAC서비스와 로드 밸런싱srvctl add servicePreferredAvailablePDB 서비스잡 클래스Resource Manager

#핵심 요약

서비스는 같은 업무를 하는 세션을 묶는 논리적 접속 단위이며, 애플리케이션은 인스턴스 이름 대신 SCAN과 서비스 이름으로 접속함

업무마다 주 실행 인스턴스(Preferred)를 나눠 두면 같은 블록을 노드끼리 주고받는 일이 줄어 Cache Fusion과 Interconnect 부담이 줄어듦
장애 때는 대체 인스턴스(Available)가 서비스를 넘겨받음

srvctl add service -pdb로 PDB에 연결된 업무용 서비스를 만들며, PDB 기본 서비스는 Preferred, Available, TAF, FAN 정책을 걸기 어려움

Scheduler 잡 클래스에 서비스를 지정하면 그 클래스의 잡은 서비스가 떠 있는 노드에서 실행됨

클라이언트 로드 밸런싱은 주소 선택을 분산하고 서버측 로드 밸런싱은 등록된 서비스, 인스턴스 상태와 부하를 이용함

#개념과 동작 원리

구분 역할
인스턴스 <INSTANCE1>, <INSTANCE2>처럼 DB를 실제로 실행하는 단위
서비스 애플리케이션 접속에 쓰는 업무용 논리 이름, 하나 또는 여러 인스턴스에서 실행 가능
SCAN 개별 노드 주소 대신 쓰는 RAC 진입점
SERVICE_NAME 접속할 업무 서비스 지정

노드를 늘리면 CPU와 메모리는 늘지만, 같은 블록을 여러 노드가 번갈아 쓰면 노드 1 캐시의 블록을 노드 2가 Interconnect로 받아 가는 Cache Fusion 전송도 늘어남
그래서 노드 수가 두 배가 돼도 처리 능력이 단순히 두 배가 되지는 않음 같은 업무의 세션을 한 인스턴스에 모으면 그 업무 블록을 로컬 Buffer Cache에서 다시 쓸 가능성이 커지고, 다른 노드에서 블록을 받는 횟수가 줄어듦 수업 자료의 정리: RAC의 장점은 고가용성과 확장성, 단점은 Interconnect 부하로 인한 성능 저하 가능성이며, 서비스로 업무별 세션과 실행 위치를 나눠 단점을 줄임

구분 역할
Preferred 정상 상태의 주 실행 인스턴스, 캐시 친화도와 운영 정책 유지
Available Preferred 장애 때 서비스를 넘겨받는 대체 인스턴스
구분 특성
PDB 기본 서비스 PDB를 열면 자동 등록, Preferred, Available과 TAF, FAN 정책 적용에 제약
업무용 서비스 srvctl로 따로 만들어 운영 접속과 서비스 정책 관리에 씀
관리 기능 서비스와의 관계
Scheduler 잡 클래스의 service 속성으로 서비스 지정, 잡은 job_class로 클래스 지정
Resource Manager 서비스나 세션 그룹별 CPU 우선순위 제어
CPU가 남으면 더 쓸 수 있고 경합할 때 설정한 소비자 그룹의 우선순위와 제한이 적용됨
부하 분산 설명
서비스 친화도 데이터 접근 패턴, 캐시 재사용, 응답시간과 부하 분포를 함께 고려
클라이언트 분산 LOAD_BALANCE=ON으로 주소 목록의 접속 대상 선택
서버측 분산 리스너에 등록된 인스턴스와 서비스 정보를 이용해 신규 접속 분산
LREG 12c 이후 로컬, 원격 리스너에 서비스와 인스턴스 상태 동적 등록
REMOTE_LISTENER 잘못 설정되면 원격 리스너에 서비스가 등록되지 않아 분산과 장애 대응에 영향

서비스 배치 효과는 배치 전후 응답시간과 세션 분포, gc 대기와 원격 블록 수신량으로 비교함(Cache Fusion)

#필수 명령어 또는 SQL

#업무별 서비스 만들기

oracle 계정 셸 (<NODE1>)객체 또는 설정을 변경함
srvctl add service -db <DB_NAME> -service GL -preferred <INSTANCE1> -available <INSTANCE2>
srvctl add service -db <DB_NAME> -service AP -preferred <INSTANCE2> -available <INSTANCE1>
srvctl start service  -db <DB_NAME> -service GL
srvctl start service  -db <DB_NAME> -service AP
srvctl status service -db <DB_NAME>
lsnrctl status

결과 해석:

수업 자료는 짧은 옵션(-d <DB_NAME> -s GL -r <INSTANCE1> -a <INSTANCE2>)으로도 적었으며 -s는 서비스 이름, -r은 Preferred, -a는 Available임

실습 기록: Service GL is running on instance(s) <INSTANCE1>, Service AP is running on instance(s) <INSTANCE2>로 나왔고, <NODE1> 리스너에는 GL, <NODE2> 리스너에는 AP가 등록됐음
GL 별칭으로 접속한 세션의 v$instance는 <INSTANCE1>이었음

접속 별칭은 HOST에 SCAN 이름, SERVICE_NAME에 업무 서비스를 적음

tnsnames.ora (클라이언트)객체 또는 설정을 변경함
GL =
  (DESCRIPTION =
    (FAILOVER = on)
    (LOAD_BALANCE = on)
    (ADDRESS = (PROTOCOL = TCP)(HOST = <SCAN_NAME>)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = GL)
      (FAILOVER_MODE = (TYPE = SELECT)(METHOD = BASIC)(RETRIES = 10)(DELAY = 1))))

결과 해석:

실습에서는 기본 서비스 별칭으로 두 번 접속하자 <INSTANCE1>, <INSTANCE2>로 번갈아 붙었고, Preferred <INSTANCE1>, Available <INSTANCE2>로 만든 order 서비스로는 <INSTANCE1>에 붙었음
수업 자료의 "무조건 1번 노드 접속"은 정상 상태의 설명이며 <INSTANCE1> 장애 때는 Available인 <INSTANCE2>로 넘어감

#PDB에 업무용 서비스 붙이기

oracle 계정 셸 (<NODE1>)객체 또는 설정을 변경함
srvctl add service -db <DB_NAME> -service svc_hr  -pdb <PDB_NAME> -preferred <INSTANCE1> -available <INSTANCE2>
srvctl add service -db <DB_NAME> -service svc_rpt -pdb <PDB_NAME> -preferred <INSTANCE2> -available <INSTANCE1>
srvctl start service  -db <DB_NAME> -service svc_hr,svc_rpt
srvctl config service -db <DB_NAME> -service svc_hr
srvctl status service -db <DB_NAME>
grid 계정 셸 (<NODE1>)조회만 함
crsctl stat res -t | grep svc
lsnrctl status | grep -i svc
SQL*Plus (SYSDBA)조회만 함
SELECT inst_id, name, pdb FROM gv$services WHERE name LIKE 'svc%' ORDER BY name, inst_id;

-- 업무 서비스로 접속한 세션에서
SELECT SYS_CONTEXT('userenv', 'con_name')      AS pdb,
       SYS_CONTEXT('userenv', 'instance_name') AS inst,
       SYS_CONTEXT('userenv', 'service_name')  AS svc
  FROM dual;

결과 해석: srvctl config service의 Pluggable database name이 연결된 PDB임
실습 기록: svc_hr은 <INSTANCE1>, svc_rpt는 <INSTANCE2>에서 실행됐고, svc_hr로 접속한 세션은 PDB1 / <INSTANCE1> / svc_hr로 나왔음
이 서비스의 장애 전환은 접속 장애 전환에 있음

#Scheduler 잡을 서비스 노드에서 실행

서비스 Preferred 잡 클래스 잡
HOT_BATCH_SERV <INSTANCE1> HOT_BATCH_CLASS JOB1, JOB2
LOW_BATCH_SERV <INSTANCE2> LOW_BATCH_CLASS JOB3
oracle 계정 셸 (<NODE1>)객체 또는 설정을 변경함
srvctl add service -db <DB_NAME> -service HOT_BATCH_SERV -preferred <INSTANCE1> -available <INSTANCE2>
srvctl add service -db <DB_NAME> -service LOW_BATCH_SERV -preferred <INSTANCE2> -available <INSTANCE1>
srvctl start service -db <DB_NAME> -service HOT_BATCH_SERV
srvctl start service -db <DB_NAME> -service LOW_BATCH_SERV
lsnrctl status | grep -E "HOT_BATCH|LOW_BATCH"
SQL*Plus (SYSDBA)객체 또는 설정을 변경함
BEGIN
  DBMS_SCHEDULER.CREATE_JOB_CLASS(
    job_class_name => 'HOT_BATCH_CLASS',
    service        => 'HOT_BATCH_SERV',
    comments       => '무거운 배치 작업 클래스');
END;
/

BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name        => 'JOB1',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN
                          INSERT INTO <USERNAME>.batch_log(job_name, inst_name, message)
                          VALUES (''JOB1'', SYS_CONTEXT(''USERENV'',''INSTANCE_NAME''), ''HOT_BATCH 작업 실행 완료'');
                          COMMIT;
                        END;',
    job_class       => 'HOT_BATCH_CLASS',
    repeat_interval => 'FREQ=MINUTELY; INTERVAL=2',
    enabled         => TRUE);
END;
/

EXEC DBMS_SCHEDULER.RUN_JOB('JOB1', use_current_session => FALSE);
SQL*Plus (SYSDBA)조회만 함
SELECT inst_id, name, network_name, goal, clb_goal
  FROM gv$active_services
 WHERE name IN ('HOT_BATCH_SERV', 'LOW_BATCH_SERV')
 ORDER BY name, inst_id;

SELECT job_class_name, service FROM dba_scheduler_job_classes
 WHERE job_class_name IN ('HOT_BATCH_CLASS', 'LOW_BATCH_CLASS');

SELECT job_name, instance_id, status, actual_start_date, run_duration, error#
  FROM dba_scheduler_job_run_details
 WHERE job_name IN ('JOB1', 'JOB2', 'JOB3')
 ORDER BY actual_start_date DESC;

결과 해석:

실습은 batch_log 테이블에 잡이 실행된 인스턴스 이름을 남겨 확인함
잡 실행 이력의 INSTANCE_ID로도 볼 수 있음

실습에서는 srvctl stop instance -d <DB_NAME> -i <INSTANCE1>로 <INSTANCE1>을 내려(안 내려가면 SHUTDOWN ABORT) HOT_BATCH_SERV가 <INSTANCE2>로 옮겨 간 것을 srvctl status service로 확인했음
그 뒤 JOB1이 <INSTANCE2>에서 실행되는지 보는 단계의 결과는 기재 없음

원래대로: srvctl start instance -d <DB_NAME> -i <INSTANCE1> 뒤 srvctl relocate service -d <DB_NAME> -s HOT_BATCH_SERV -oldinst <INSTANCE2> -newinst <INSTANCE1>

정리: DBMS_SCHEDULER.DROP_JOB, DROP_JOB_CLASS, 로그 테이블 삭제, srvctl stop service, srvctl remove service

#서비스별 접속 분포

SQL*Plus (SYSDBA)조회만 함
SHOW PARAMETER remote_listener

SELECT s.service_name, s.inst_id, COUNT(*) AS session_count
  FROM gv$session s
 WHERE s.service_name IN ('<SERVICE_NAME_1>', '<SERVICE_NAME_2>')
 GROUP BY s.service_name, s.inst_id
 ORDER BY s.service_name;

결과 해석: 서비스별 인스턴스 접속 분포 확인이 목적이며 집계 결과 행은 기재 없음

#사용 조건과 주의사항

서비스 친화도 실습에서는 MMNL을 RAC 전용, 서비스 자동 배치 담당으로 설명하면서 같은 본문에서 그 주장에 근거 확인이 필요하다고 적었음

서버 분산 실습의 반복 스크립트는 10회인데 부하 전 분포는 노드별 25회라고 적어 서로 맞지 않음

정적 등록 항목만으로 로드 밸런싱 불가를 단정하는 설명과 GOAL_NONE을 모든 접속 분산의 비활성화로 보는 설명은 실습 자체의 주의와 함께 보류함

Clusterware가 관리하는 서비스는 srvctl 정의가 기준이며, DBMS_SERVICE로 바꾼 값은 재기동 때 덮어써질 수 있음

인스턴스를 내려 서비스 전환을 보는 단계는 그 인스턴스의 모든 세션을 끊으므로 실습 환경에서만 함

SEO_HKabsumveritas@gmail.comBuilt with Claude Code & Codex

마지막 갱신 개인 학습 기록이며 운영 환경 적용 전 공식 문서 확인 필요

두 글자 이상 입력, 위아래 화살표로 이동하고 Enter로 열기