데이터베이스 연구실.log

RAC 병렬 처리와 복구 성능

RAC 병렬 실행의 노드 제한, fast_start_mttr_target 설정과 생존 노드 alert log의 복구 시간 관찰

T_CLAIMTARGET_MTTR병렬 쿼리instance_groupsparallel_instance_groupInstance Recoveryfast_start_mttr_targetGV$INSTANCE_RECOVERYESTIMATED_MTTRDBWR checkpoint buffers written

#핵심 요약

RAC 병렬 실행은 한 서버의 CPU, 메모리 대신 여러 노드 자원을 함께 써서 대량 조회, 집계 시간을 줄일 수 있음
대신 노드 사이에 블록과 중간 결과가 오가며 인터커넥트 통신이 생겨, 데이터 이동이 많거나 인터커넥트가 바쁘면 이득보다 비용이 커질 수 있음

instance_groups(인스턴스별 소속 그룹)와 parallel_instance_group(세션이 쓸 그룹)으로 병렬 실행에 참여할 인스턴스를 제한함

인스턴스가 죽으면 생존 인스턴스가 그 인스턴스의 리두로 복구함
fast_start_mttr_target은 목표 복구 시간(초)이며, 0이면 목표 기반 복구 튜닝이 꺼진 상태임

목표를 줄이면 평상시 체크포인트 쓰기(DBWR checkpoint buffers written)가 늘어남
복구 시간과 평상시 쓰기 비용을 함께 봄

#개념과 동작 원리

RAC 인스턴스 복구는 생존 인스턴스의 SMON이 죽은 인스턴스를 다시 띄우지 않고 그 redo thread를 읽어 대신 함

  1. GRD 재구성: 죽은 노드가 맡던 글로벌 자원 정보(어느 노드에 최신 블록이 있는지)를 생존 노드로 다시 나누며, 이 동안 관련 자원 접근이 잠시 멈춤
  2. Roll forward: 커밋됐지만 데이터 파일에 아직 반영되지 않은 변경을 리두로 다시 적용함
  3. Roll back: 커밋되지 않은 트랜잭션을 UNDO로 취소함

장애 노드 사용자가 TAF로 생존 노드에 넘어와도, 그 순간 생존 노드는 복구에 CPU와 I/O를 크게 쓰고 GRD 재구성 동안 일부 블록 접근이 멈춰 넘어온 세션이 한동안 일을 못 할 수 있음
장애 전 DML이 많을수록 적용할 리두가 많아 이 시간이 길어짐
fast_start_mttr_target을 낮추면 체크포인트와 dirty buffer 쓰기가 잦아져 복구는 빨라지지만 평상시 DBWR I/O가 늘어 DML 성능이 떨어질 수 있음 수업 자료에 나온 _fast_start_instance_recovery_target(GRD 재구성 목표)은 이전 버전의 숨은 파라미터라 19c에서는 조회하거나 바꾸지 않음

병렬 실행 비교 항목 확인 내용
실행 시간 병렬 실행의 처리 시간 변화
인스턴스 분포 병렬 프로세스가 도는 인스턴스
gc 대기 병렬 실행에 따른 gc 대기 증가 여부
인터커넥트 트래픽 노드 간 통신량 증가 여부
CPU 사용률 실행 전후 변화

실습에서는 같은 부하로 단일 노드 병렬과 다중 노드 병렬을 비교해 효과를 판단하라고 적었음
인터커넥트 점검은 Interconnect와 RAC 대기에 있음

복구 관련 값 의미
fast_start_mttr_target 목표 복구 시간(초)
동적 파라미터
GV$INSTANCE_RECOVERY.TARGET_MTTR 인스턴스별 복구 목표
ESTIMATED_MTTR 지금 장애가 나면 예상되는 복구 시간(초)

실습에서는 11g 시절의 숨은 파라미터 _fast_start_instance_recovery_target을 19c에서 조회해 보이지 않는 것을 확인했음
단일 인스턴스의 인스턴스 복구 개념은 장애 유형와 함께 봄

#필수 명령어 또는 SQL

#병렬 프로세스 분포와 실행 노드 제한

SQL*Plus (SYSDBA)조회만 함
SELECT inst_id, process, program
  FROM gv$session
 WHERE program LIKE '%(P0%';

SELECT /*+ parallel(a) parallel(b) */ COUNT(*)
  FROM dba_objects a, dba_objects b;

결과 해석: 병렬 쿼리를 실행하는 동안 첫 조회를 다시 하면 인스턴스별 병렬 프로세스(P0nn) 분포를 볼 수 있음

SQL*Plus (SYSDBA)객체 또는 설정을 변경함
ALTER SYSTEM SET instance_groups = seoul, busan SCOPE = SPFILE SID = '<INSTANCE1>';
ALTER SYSTEM SET instance_groups = seoul SCOPE = SPFILE SID = '<INSTANCE2>';
-- 두 인스턴스 재기동
ALTER SESSION SET parallel_instance_group = busan;

결과 해석: 1번 인스턴스만 busan 그룹에 속하므로, 세션 그룹을 busan으로 두고 병렬 쿼리를 실행하면 병렬 슬레이브가 1번 노드에서만 돌았음
실습에서는 SHUTDOWN IMMEDIATE와 STARTUP을 각 노드에서 실행해 재기동했음
instance_groups가 19c에서 권장되는 방식인지는 기재 없음

#복구 목표와 예측치

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

SELECT inst_id, target_mttr, estimated_mttr, recovery_estimated_ios
  FROM gv$instance_recovery
 ORDER BY inst_id;

결과 해석:

실습 결과: fast_start_mttr_target 0, fast_start_io_target 0, fast_start_parallel_rollback LOW, 두 인스턴스 TARGET_MTTR 0

SQL*Plus (SYSDBA)객체 또는 설정을 변경함
ALTER SYSTEM SET fast_start_mttr_target = 1200 SCOPE = BOTH SID = '*';
SQL*Plus (SYSDBA)조회만 함
SELECT inst_id, value
  FROM gv$sysstat
 WHERE name = 'DBWR checkpoint buffers written'
 ORDER BY inst_id;

결과 해석:

실습에서는 목표를 600초로 줄이고 몇 분 동안 DML을 한 뒤 다시 조회해 증가 폭이 커지는 것(평상시 쓰기 비용)을 보게 했음
SID = '*'는 모든 인스턴스에 같은 목표를 줌

#인스턴스 장애와 실제 복구 시간

실습에서는 1번 노드에서 20만 건 테이블을 만들고 전체를 UPDATE한 채 커밋하지 않은 상태로 두었음

장애를 일으키기 직전에 생존할 2번 인스턴스의 CDB 루트에서 아래 시각을 기록해 <FAILURE_START>로 사용함
DB 시간대와 소수 초를 포함한 값을 그대로 사용함

SQL*Plus (생존 2번 인스턴스, CDB 루트 SYSDBA)조회만 함
SELECT TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM') AS failure_start FROM dual;
OS (oracle 사용자)인스턴스 또는 서비스 중단이 필요함
srvctl stop instance -db <DB_NAME> -instance <INSTANCE1> -stopoption abort
SQL*Plus (생존 2번 인스턴스, CDB 루트 SYSDBA)조회만 함
SELECT originating_timestamp, partition, record_id, message_text
  FROM v$diag_alert_ext
 WHERE originating_timestamp >= TO_TIMESTAMP_TZ(
         '<FAILURE_START>', 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')
   AND REGEXP_LIKE(message_text, 'instance recovery|reconfiguration', 'i')
 ORDER BY originating_timestamp, partition, record_id;

결과 해석: 타임스탬프가 메시지와 함께 조회되므로 텍스트 로그에서 시각 행이 분리되는 문제를 피할 수 있음
기록한 시각 이후의 메시지에서 장애 인스턴스의 redo thread와 일치하는 Beginning instance recovery와 Completed instance recovery를 짝지음
이번 복구의 완료 메시지가 없으면 재조회하며, 이전 장애의 완료 메시지를 선택하지 않음
짝지은 시작, 완료의 ORIGINATING_TIMESTAMP 차이를 초로 환산해 인스턴스 복구 구간으로 보고하고, 재구성 시작, 완료 시각은 따로 기록함
메시지에서 대상 thread나 시작, 완료 짝을 확인할 수 없으면 실측 시간은 확인 불가임
1번 인스턴스를 다시 올리기 전에 2번 노드에서 이번 복구가 끝났는지 확인함
실습에서는 재기동 후 미커밋 변경이 롤백되어 변경된 행이 0건인 것을 확인했음

#확인 문제: 복구 목표 5분과 실측 보고

상황: 2번 노드가 갑자기 꺼졌을 때 1번 노드로 넘어온 사용자 화면이 몇 분 멈췄음
복구가 5분 안에 끝나도록 맞추고, 현재 설정의 예상 복구 시간과 실제 장애 때 걸린 시간을 보고서에 넣어 달라는 요청

SQL*Plus (실습 계정, 2번 노드, 커밋하지 않고 둠)객체 또는 설정을 변경함
CREATE TABLE t_claim AS
  SELECT level AS id, rpad('a', 100, 'a') AS memo FROM dual CONNECT BY level <= 200000;
UPDATE t_claim SET memo = rpad('b', 100, 'b');
SQL*Plus (SYSDBA, 1번 노드)객체 또는 설정을 변경함
ALTER SYSTEM SET fast_start_mttr_target = 300 SCOPE = BOTH SID = '*';
SELECT inst_id, target_mttr, estimated_mttr FROM gv$instance_recovery ORDER BY inst_id;

결과 해석:

장애 직전에 생존할 1번 인스턴스에서 위 시각 조회를 실행해 이번 <FAILURE_START>를 기록함

OS (1번 노드, oracle)인스턴스 또는 서비스 중단이 필요함
srvctl stop instance -db <DB_NAME> -instance <INSTANCE2> -stopoption abort

결과 해석:

생존 1번 인스턴스의 CDB 루트에서 위 V$DIAG_ALERT_EXT 조회를 실행함
이번 장애 대상 <INSTANCE2>의 thread에 대한 복구 시작, 완료와 타임스탬프를 확인한 뒤에만 시간을 계산하고 2번 인스턴스를 다시 올림

OS (1번 노드, oracle)객체 또는 설정을 변경함
srvctl start instance -db <DB_NAME> -instance <INSTANCE2>
SQL*Plus (실습 계정, 1번 노드)조회만 함
SELECT COUNT(*) FROM <SCHEMA>.t_claim WHERE memo LIKE 'b%';

결과 해석:

장애 대상은 <INSTANCE2>이고 복구 기록은 생존 1번 인스턴스의 alert log에 남음

예상값: TARGET_MTTR 300, 재기동 뒤 미커밋 변경이 롤백돼 조회 결과 0

보고서에는 TARGET_MTTR, ESTIMATED_MTTR, alert log 실측 시간을 함께 적고, 목표 300초 설정 전후의 체크포인트 쓰기와 DML 성능 변화도 확인함

실습이 끝나면 DROP TABLE <SCHEMA>.t_claim PURGE로 지움
실행 결과 확인 불가

SEO_HKabsumveritas@gmail.comBuilt with Claude Code & Codex

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

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