[Oracle] RMAN으로 백업 및 복구하기

예전 글에서는 Oracle Data Pump 유틸리티(expdp/impdp)를 사용하여 스키마를 이전하는 절차를 알아봤는데요, 이번 글에서는 RMAN으로 Oracle Database를 백업 및 복구하는 절차를 정리해 보고자 합니다. 아직까지 백업/복구 모의훈련을 위한 가상서버(VM)가 준비되지 않아서 먼저 정리를 하고, VM이 준비되면 모의훈련을 하면서 부족한 부분을 보충해 나갈 예정입니다. 모의훈련이 끝나면 백업/복구 절차가 검증되었다고 이 글에 남기도록 하겠습니다. 혹시 전문DBA께서 이 글을 보셨다면 부족한 부분에 많은 의견부탁드립니다.

  1. RMAN 환경 구성 및 기본 사용법 알아보기
  2. RMAN으로 백업하기
  3. RMAN으로 복구하기
    1. 전체 복구하기
    2. 특정 데이터파일만 복구하기
    3. 다른 디스크에 복구하기
    4. 다른 데이터베이스 서버에 복구하기(복제 및 이관)

1. RMAN 환경 구성 및 기본 사용법 알아보기

  1. SID 확인: $ORACLE_SID는 v$instance 뷰를 통해 확인합니다.
    SQL> SELECT instance_name AS SID FROM v$instance;
    
  2. LOG모드 확인: ARCHIVELOG인지 확인합니다.
    SQL> SELECT LOG_MODE, OPEN_MODE FROM V$DATABASE;
    LOG_MODE     OPEN_MODE
    ------------ --------------------
    ARCHIVELOG   READ WRITE
    
    --또는
    
    SQL> archive log list;
    Database log mode              Archive Mode
    Automatic archival             Enabled
    Archive destination            USE_DB_RECOVERY_FILE_DEST
    Oldest online log sequence     97419
    Next log sequence to archive   97423
    Current log sequence           97423
    
  3. Retention Policy 설정: 백업본을 며칠간 보관할지 결정하세요. (예: 7일)
    RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;
    
  4. Controlfile Autobackup: DB 구조 변경 시 백업이 자동 생성되도록 설정하세요.
    -- "/backup/path/to/autobackup" 디렉토리는 미리 생성해야 합니다.
    RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
    RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '/backup/path/to/autobackup/conf_%F';
    
  5. 병렬 처리(PARALLELISM) 설정: 채널을 2개 할당하여 백업 속도를 높이면서도 서비스 부하를 고려합니다.
    RMAN> show device type; 명령으로 병렬 처리 채널를 확인할 수 있습니다.
    RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 2;
    
  6. 백업 효율 극대화: 동일한 읽기 전용(Read-Only) 테이블스페이스나 이미 백업된 아카이브 로그 등을 지능적으로 제외하므로, 특히 매일 아카이브 로그를 백업하는 환경에서 불필요한 I/O를 획기적으로 줄여줍니다.
    RMAN> CONFIGURE BACKUP OPTIMIZATION ON;
    

2. RMAN으로 백업하기

  • 백업 전략
    • 일요일은 Full Backup(LEVEL 0), 월요일~토요일은 Cumulative Incremental Backup(LEVEL 1 CUMULATIVE)
    • Archive Log File, Controlfile, SPFILE은 10분 단위로 백업
    • Lock 파일을 사용해서 백업 프로세스의 중복 실행 방지(10분 이상 걸리는 백업이 있는 경우 대비)
  • 백업 스크립트 작성(rman_backup.sh).
    CONFIGURE CONTROLFILE AUTOBACKUP ON; 설정을 하면 Control File과 SPFILE을 별도로 백업할 필요가 없습니다. 왜냐하면 Autobackup File에는 Control File과 SPFILE이 포함되어 있기 때문입니다. RMAN 백업 스크립트에서 사용하는 FORMAT 문자열의 치환 변수(Substitution Variables)는 아래와 같은 기능을 합니다.
    • %F(Control File Autobackup Format): “c-DBID-YYYYMMDD-순번”으로 표시합니다.
    • %d(Database Name): 대상 데이터베이스의 이름(DB_NAME)을 표시합니다.
    • %T(Year/Month/Day): 백업이 수행된 날짜를 YYYYMMDD 형식으로 표시합니다.
    • %U(System Generated Unique ID): 8자리 고유 식별자 + 세트 번호 + 피스 번호가 결합된 형태입니다.
    $ vi /path/to/scripts/rman_backup.sh
    #!/bin/bash
    #crontab -e
    #*/10 * * * * /path/to/scripts/rman_backup.sh > /dev/null 2>&1
    
    check_error() {
        if [ $1 -ne 0 ]; then
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $2 failed at $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
            echo "Stopping backup process." >> $LOG_FILE
            exit 1
        fi
    }
    
    #############################################
    # User Environment
    #############################################
    export ORACLE_SID=<SID>
    export ORACLE_BASE="/u01/app/oracle"
    export ORACLE_HOME="${ORACLE_BASE}/product/11.2.0.4.0/dbhome_1"
    export PATH=$ORACLE_HOME/bin:$PATH
    export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
    
    #############################################
    # Date and Backup Path Variables
    #############################################
    BASE_DIR=$(cd "$(dirname "$0")" && pwd)
    SCRIPT_NAME=$(basename "$0" .sh)
    
    DATE=$(date +%Y%m%d)
    DAY_OF_WEEK=$(date +%u)   # 1=Mon ... 7=Sun
    HOUR_MIN=$(date +%H%M)
    
    BACKUP_BASE="/backup_data"
    BACKUP_DIR="${BACKUP_BASE}/${DATE}"  
    BACKUP_DATA="${BACKUP_DIR}/database"
    BACKUP_ARCH="${BACKUP_DIR}/archivelog"
    BACKUP_CTRL="${BACKUP_DIR}/controlfiles"
    
    LOG_DIR="${BACKUP_BASE}/logs/$(date +%Y%m)"
    LOG_FILE="${LOG_DIR}/backup_$(date +%Y%m%d).log"
    if [ ! -d "$LOG_DIR" ]; then
        mkdir -p "$LOG_DIR"
    
        check_error $? "${DIR} Creation"
    fi
    
    DIRS_TO_CREATE=("${BACKUP_DATA}" "${BACKUP_ARCH}" "${BACKUP_CTRL}")
    for DIR in "${DIRS_TO_CREATE[@]}"; do
        if [ ! -d "$DIR" ]; then
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] Directory $DIR does not exist. Creating..." >> $LOG_FILE
            mkdir -p "$DIR"
    
            check_error $? "${DIR} Creation"
        fi
    done
    
    #############################################
    # Backup Type Decision
    #############################################
    #Uncomment two lines before manually executing this script at the first time, and then comment them below again
    #DAY_OF_WEEK="7"
    #HOUR_MIN="0000"
    if [ "${DAY_OF_WEEK}" == "7" ]; then
        LEVEL=0
        TAG_NAME="WEEKLY_LEVEL0_${DATE}"
    else
        LEVEL=1
        TAG_NAME="DAILY_LEVEL1_${DATE}"
    fi
    
    #Differential Incremental Backup = "", Cumulative Incremental Backup = "CUMULATIVE"
    TYPE="CUMULATIVE"
    
    LOCKFILE="/tmp/rman_backup.lock"
    if [ -e "${LOCKFILE}" ]; then
        OLD_PID=$(cat "${LOCKFILE}")
        
        if ps -p "${OLD_PID}" > /dev/null 2>&1; then
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] [CRITICAL] Another backup (PID: ${OLD_PID}) is still running. Exiting to prevent overlap." >> "$LOG_FILE"
            exit 1
        else
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] Stale lock file found (PID: ${OLD_PID} is dead). Cleaning up and starting new backup." >> "$LOG_FILE"
            rm -f "${LOCKFILE}"
        fi
    fi
    echo $$ > "${LOCKFILE}"
    
    if [ "${HOUR_MIN}" == "0000" ]; then
        echo "#########################################################" >> $LOG_FILE
        echo "[$(date '+%H:%M:%S')] START: DATABASE LEVEL ${LEVEL} ${TYPE} BACKUP" >> $LOG_FILE
        echo "#########################################################" >> $LOG_FILE
    
        echo "---------------------------------------------------------" >> $LOG_FILE
        echo "ARCHIVE LOG SWITCH Started at $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
        echo "---------------------------------------------------------" >> $LOG_FILE
        sqlplus -s '/ as sysdba' <<EOF1
            ALTER SYSTEM ARCHIVE LOG CURRENT;
            EXIT;
    EOF1
        check_error $? "Archive Log Switch"
    	sleep 30
        
        echo "---------------------------------------------------------" >> $LOG_FILE
        echo "DATABASE LEVEL ${LEVEL} BACKUP Started at $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
        echo "---------------------------------------------------------" >> $LOG_FILE
    
        rman target / log=${LOG_FILE} append >>EOF2
            CONFIGURE CONTROLFILE AUTOBACKUP ON;
            CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '${BACKUP_CTRL}/%F';
    # CONTROL_FILE_RECORD_KEEP_TIME parameter = RETENTION POLICY + 1 ~ 2 days
    # ALTER SYSTEM SET CONTROL_FILE_RECORD_KEEP_TIME = 15 SCOPE=BOTH;
    #        CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 14 DAYS;
    #        CONFIGURE BACKUP OPTIMIZATION ON;
    #        CONFIGURE DEVICE TYPE DISK PARALLELISM 2;
    #        CONFIGURE ARCHIVELOG DELETION POLICY TO [APPLIED ON ALL STANDBY] BACKED UP 1 TIMES TO DISK;
            CONFIGURE SNAPSHOT CONTROLFILE NAME TO '${BACKUP_BASE}/snapcf_${ORACLE_SID}.f';
    
            RUN {
    # Clean up ghost data that exists only in control file, but does not exist in the actual files.
                CROSSCHECK BACKUP;
                CROSSCHECK ARCHIVELOG ALL;
                DELETE NOPROMPT EXPIRED BACKUP;
                DELETE NOPROMPT EXPIRED ARCHIVELOG ALL;
    
                ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
                ALLOCATE CHANNEL c2 DEVICE TYPE DISK;
                ALLOCATE CHANNEL c3 DEVICE TYPE DISK;
                ALLOCATE CHANNEL c4 DEVICE TYPE DISK;
    
                BACKUP AS COMPRESSED BACKUPSET
                    INCREMENTAL LEVEL ${LEVEL} ${TYPE}
                    DATABASE
                    FORMAT '${BACKUP_DATA}/datafile_%d_%T_%U.bkp'
                    TAG '${TAG_NAME}';
    #                FORCE;
    
    #            BACKUP CURRENT CONTROLFILE
    #                FORMAT '${BACKUP_CTRL}/ctrl_%d_%T_%U.bkp'
    #                TAG 'CONTROLFILE_BACKUP_${DATE}';
    
    #            BACKUP SPFILE
    #                FORMAT '${BACKUP_CTRL}/spfile_%d_%T_%U'
    #                TAG 'SPFILE_BACKUP_${DATE}';
    
                RELEASE CHANNEL c1;
                RELEASE CHANNEL c2;
                RELEASE CHANNEL c3;
                RELEASE CHANNEL c4;
    
    # Delete all backed-up files from ${BACKUP_BASE} in accordance with the RETENTION POLICY
                REPORT OBSOLETE;
                DELETE NOPROMPT OBSOLETE;
    
    # Delete original archive log files older than 14 days after being successfully backed up at least once
                DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DISK COMPLETED BEFORE 'SYSDATE - 14';
            }
            EXIT;
    EOF2
    
        check_error $? "Database Backup & Controlfile Backup & Cleanup"	
    	
        echo "---------------------------------------------------------" >> $LOG_FILE
        echo "BACKUP DIRECTORIES CLEANING Started at $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
        echo "---------------------------------------------------------" >> $LOG_FILE
        if [ -n "${BACKUP_BASE}" ]; then
            find "${BACKUP_BASE}" -type f ! -path "*logs*" -mtime +30 -exec rm -f {} \;
            find "${BACKUP_BASE}"/logs -type f -mtime +90 -exec rm -f {} \;
            find "${BACKUP_BASE}" -mindepth 1 -type d -empty -mtime +2 -exec rmdir {} \;
        fi
    fi
    
    echo "---------------------------------------------------------" >> $LOG_FILE
    echo "ARCHIVELOG BACKUP Started at $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
    echo "---------------------------------------------------------" >> $LOG_FILE
    DATETIME=$(date +%Y%m%d%H%M)
    rman target / log=${LOG_FILE} append <<EOF3
        CONFIGURE CONTROLFILE AUTOBACKUP ON;
        CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '${BACKUP_CTRL}/%F';
        CONFIGURE SNAPSHOT CONTROLFILE NAME TO '${BACKUP_BASE}/snapcf_${ORACLE_SID}.f';
    
        BACKUP AS COMPRESSED BACKUPSET
            ARCHIVELOG ALL NOT BACKED UP 1 TIMES
    #        DELETE INPUT
            FORMAT '${BACKUP_ARCH}/arch_%d_%T_%U.bkp'
            TAG 'ARCHIVELOG_BACKUP_${DATETIME}';
    #        FORCE;
    
    #    BACKUP CURRENT CONTROLFILE
    #        FORMAT '${BACKUP_CTRL}/ctrl_%d_%T_%U.bkp'
    #        TAG 'CONTROLFILE_BACKUP_${DATETIME}';
    
    #    BACKUP SPFILE
    #        FORMAT '${BACKUP_CTRL}/spfile_%d_%T_%U'
    #        TAG 'SPFILE_BACKUP_${DATETIME}';
    
        EXIT;
    EOF3
    
    check_error $? "Archivelog Backup"
    rm -f "${LOCKFILE}"
    
  • crontab에 등록하여 10분마다 자동으로 실행합니다.
  • 직접 위 백업 스크립트를 실행했다면 아래 쿼리를 통해 현재 병렬로 작동 중인 채널의 수를 확인할 수 있습니다.
    SELECT SID, SERIAL#, CONTEXT, SOFAR, TOTALWORK, ROUND(SOFAR/TOTALWORK*100, 2) AS "%_COMPLETE"
    FROM V$SESSION_LONGOPS
    WHERE OPNAME LIKE 'RMAN%'
      AND TOTALWORK > 0
      AND SOFAR < TOTALWORK;
    
  • 모든 RMAN 백업데이터 및 이력과 불필요한 Archivelog를 삭제하려면 아래 스크립트를 실행합니다. 실행 결과는 RMAN> LIST BACKUP SUMMARY; 명령으로 확인합니다.
    #!/bin/bash
    
    #############################################################
    # User Environment                                          #
    #############################################################
    export ORACLE_SID=<SID>
    export ORACLE_BASE="/u01/app/oracle"
    export ORACLE_HOME="/u01/app/oracle/product/11.2.0.4/dbhome_1"
    export PATH=$ORACLE_HOME/bin:$PATH
    
    BACKUP_BASE="/mnt/nas/cdev/backup"
    LOCKFILE="/tmp/rman_backup.lock"
    
    if [ "$1" != "force" ]; then
        echo "Usage: $0 force (This will delete ALL backups)"
        exit 1
    fi
    
    #############################################################
    # OS Level Cleanup (Physical Files & Dirs)                  #
    #############################################################
    
    echo "--- Deleting all physical files in ${BACKUP_BASE} ---"
    if [ -n "${BACKUP_BASE}" ]; then
        rm -rf "${BACKUP_BASE:?}"/*
    fi
    
    rm -f "${LOCKFILE}"
    
    #############################################################
    # RMAN Cleanup All (Database+Archivelog+Controlfile+SPFILE) #
    #############################################################
    
    rman target / >gt;EOF
        CROSSCHECK BACKUP;
        CROSSCHECK COPY;
        CROSSCHECK ARCHIVELOG ALL;
    
        DELETE NOPROMPT EXPIRED BACKUP;
        DELETE NOPROMPT EXPIRED COPY;
        DELETE NOPROMPT EXPIRED ARCHIVELOG ALL;
    
        DELETE NOPROMPT BACKUP;
        DELETE NOPROMPT COPY;
    
    # Uncomment to delete unnecessary archivelog files as needed
    #    DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-14';
    #    DELETE NOPROMPT ARCHIVELOG ALL UNTIL SEQUENCE 시퀀스번호;
    #    DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DISK COMPLETED BEFORE 'SYSDATE - 14';
    #    DELETE NOPROMPT ARCHIVELOG ALL APPLIED ON STANDBY;
    #    DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DISK APPLIED ON STANDBY;
    
        REPORT OBSOLETE;
        DELETE NOPROMPT OBSOLETE;
        EXIT;
    EOF
    
    echo "--- Cleanup Completed ---"
    

3-1. 전체 복구하기

  • 테이테베이스를 MOUNT 상태로 올린 후 복구를 시작하세요.
    RMAN> SHUTDOWN ABORT; (이미 DB가 shutdown 상태라면 생략)
    RMAN> STARTUP MOUNT;
    RMAN> RESTORE DATABASE;
    RMAN> RECOVER DATABASE;
    RMAN> ALTER DATABASE OPEN;
    

3-2. 특정 데이터파일만 복구하기

  • V$RECOVER_FILE 뷰 조회 시 ERROR 컬럼이 OFFLINE NORMAL인 경우는 관리자에 의한 정상적 오프라인 상태이며, 그 외 CANNOT OPEN, FILE NOT FOUND, I/O ERROR 등의 메시지가 발생할 경우에만 실제 물리적 장애로 간주하여 RMAN 복구 절차를 수행합니다.
    SELECT file#, ERROR 
    FROM   v$recover_file
    WHERE  error <> 'OFFLINE NORMAL';
    
  • sqlplus / as sysdba에서 쿼리를 실행해 스크립트를 추출한 후, rman target /에 접속하여 FILE_OFFLINE -> RMAN_RESTOR -> RMAN_RECOVER -> FILE_ONLINE 순으로 실행합니다.
    SELECT d.name AS DATAFILE_NAME, 
           'ALTER DATABASE DATAFILE ' || r.file# || ' OFFLINE;' AS FILE_OFFLINE,
           'RESTORE DATAFILE ' || r.file# || ';' AS RMAN_RESTOR,
           'RECOVER DATAFILE ' || r.file# || ';' AS RMAN_RECOVER,
           'ALTER DATABASE DATAFILE ' || r.file# || ' ONLINE;' AS FILE_ONLINE
    FROM   v$datafile d,
           v$recover_file r
    WHERE  d.file# = r.file#
    AND    r.error <> 'OFFLINE NORMAL';
    

3-3. 다른 디스크에 복구하기

원래 데이터파일이 있던 디스크가 물리적으로 파손되었거나(전체 복구), 용량 부족으로 인해 새로운 경로로 파일을 옮겨서 복구(데이터파일 복구)해야 할 때 사용합니다. 단순히 RESTORE만 하면 원래 경로로 돌아가려 하기 때문에, RMAN에게 “백업본을 이 새로운 경로에 풀어라”라고 명령하는 것이 핵심입니다.

  • 전체 데이터베이스를 다른 디스크에 복구하려면,3-1 전체 복구하기“와 동일하게 테이테베이스는 MOUNT 상태여야 합니다.
    -- SET NEWNAME : 모든 데이터 파일들의 새 위치를 '/path/to/%U'로 지정합니다. ASM(Automatic Storage Management) 환경에서는 '+DATA'로 변경합니다.
    -- SWITCH DATAFILE ALL : 데이터 파일의 새 위치를 인식하도록 control file을 업데이트합니다.
    RMAN> SHUTDOWN ABORT; (이미 DB가 shutdown 상태라면 생략)
    RMAN> STARTUP MOUNT;
    RMAN> RUN {
        SET NEWNAME FOR DATABASE TO '/path/to/%U';
        RESTORE DATABASE;
        SWITCH DATAFILE ALL;
        RECOVER DATABASE;
    }
    RMAN> ALTER DATABASE OPEN;
    
  • 특정 데이터파일/테이블스페이스만 다른 디스크로 복구하려면,3-2. 특정 데이터파일만 복구하기“와 동일하게 테이테베이스는 OPEN 상태여야 합니다.
    RMAN> ALTER DATABASE DATAFILE file# OFFLINE;
    RMAN> RUN {
        SET NEWNAME FOR DATAFILE file# TO '/path/to/DATAFILE_NAME.dbf';
        RESTORE DATAFILE file#;
        SWITCH DATAFILE file#;
        RECOVER DATAFILE file#;
    }
    RMAN> ALTER DATABASE DATAFILE file# ONLINE;
    

3-4. 다른 데이터베이스 서버에 복구하기(복제 및 이관)

이 과정은 보통 ‘Database Duplicate’ 또는 ‘DR(Disaster Recovery) 구축’이라고 부릅니다. 운영 서버의 데이터를 전혀 다른 서버(Auxiliary)로 옮겨서 동일한 DB를 하나 더 만드는 과정입니다. 실무에서는 운영 데이터를 개발 서버로 이관하거나, 서버 장비 교체(Migration) 시에 가장 많이 사용됩니다.

  • 사전 준비 사항 (운영자 Action): 다른 서버에 복구하기 위해서는 환경 설정이 가장 중요합니다.
    1. 비밀번호 파일 동기화: 운영 서버의 비밀번호 파일을 복사한 후 이름을 변경하여 사용할 수 있으나($ORACLE_HOME/dbs/orapw<SID>), orapwd 명령어를 사용해서 새 비밀번호 파일을 생성하는 것을 추천합니다.
      << 대상 서버 >>
      ---- 복사해 온 비밀번호 파일의 이름을 변경하는 경우,
      $ mv $ORACLE_HOME/dbs/orapw<운영SID> $ORACLE_HOME/dbs/orapw<대상SID>
      
      ---- 오라클의 orapwd 명령어를 사용하는 경우,
      -- 데이터베이스 관리자(SYSDBA) 권한으로 원격 접속할 때 필요한 패스워드 파일을 생성하거나 수정하는 도구
      -- entries=10: 10개의 비밀번호 저장, force=y: 이미 파일이 존재할 경우 덮어쓰기
      $ orapwd file=$ORACLE_HOME/dbs/orapw<SID> password=sys비밀번호 entries=10 force=y
      
    2. 환경 파일 설정 (PFILE): 운영 서버의 pfile(init<SID>.ora) 파일을 복사하여 대상 서버에 맞게 수정합니다. 특히 pfile에 설정된 디렉토리들은 미리 생성해 줘야 합니다. 그렇지 않으면 start NOMOUNT 명령어 실행 시
      << 운영 서버 >>
      ---- spfile 저장 경로를 확인합니다. 출력되지 않으면 pfile($ORACLE_HOME/dbs/init<SID>)를 사용하는 겁니다.
      SELECT name, value AS SPFILE_PATH
      FROM   v$parameter
      WHERE  name = 'spfile';
      
      ---- spfile를 통해 pfile을 생성합니다.
      -- (DB가 기동 중일 때, PFILE경로를 설정하지 않으면 기본 경로인 $ORACLE_HOME/dbs/init<SID>.ora에 생성)
      SQL> CREATE PFILE='?/dbs/init<운영SID>.ora_yyyymmdd' FROM SPFILE;
      -- (DB가 기동 중이지 않을 때, pfile 및 spfile의 경로를 지정합니다.) 
      SQL> CREATE PFILE='?/dbs/init<운영SID>.ora_yyyymmdd' FROM SPFILE='SPFILE_PATH';
      
      << 대상 서버 >>
      ---- 복사해 온 pfile의 이름을 변경합니다.
      $ mv $ORACLE_HOME/dbs/init<운영SID>.ora_yyyymmdd $ORACLE_HOME/dbs/init<대상SID>.ora
      
      ---- pfile 파일의 내용을 대상 서버에 맞게 수정합니다.(예시)
      $ vi $ORACLE_HOME/dbs/init<대상SID>.ora
      *.audit_file_dest=
      *.control_files=
      *.core_dump_dest=
      *.control_files=
      *.db_create_file_dest=
      *.db_create_online_log_dest_1=
      *.db_recovery_file_dest=
      
    3. 정적 리스너 등록(listener 유저): 정적 리스너(Static Listener) 설정은 DB가 꺼져 있거나 NOMOUNT 상태일 때도 외부(특히 RMAN)에서 접속할 수 있게 해주는 필수 관문입니다. Oracle Grid Infrastructure(GI)가 설치된 경우에는 grid 유저로 정적 리스너를 시작($ ps -ef | grep ohasd)해야 합니다. 그 이외의 경우에는 oracle 유저로 정적 리스너를 시작합니다.
      $ vi $ORACLE_HOME/network/admin/listener.ora
      # 1. 리스너의 네트워크 주소 정의
      LISTENER_DG =
        (DESCRIPTION_LIST =
          (DESCRIPTION =
            (ADDRESS = (PROTOCOL = TCP)(HOST = 대상서버_IP주소)(PORT = 1521))
            (ADDRESS = (PROTOCOL = IPC)(KEY = LISTENER_DG))
          )
        )
      
      # 2. 리스너가 강제로 서비스할 DB 목록 설정
      SID_LIST_LISTENER_DG =
        (SID_LIST =
          (SID_DESC =
            (GLOBAL_DBNAME = 대상1DBNAME)              # 외부에서 접속할 서비스명
            (ORACLE_HOME = /oracle_home/path/to)      # DB 홈 경로
            (SID_NAME = 대상1SID)                      # 대상 인스턴스 SID
          )
          (SID_DESC =
            (GLOBAL_DBNAME = 대상2DBNAME)              # 외부에서 접속할 서비스명
            (ORACLE_HOME = /oracle_home/path/to)      # DB 홈 경로
            (SID_NAME = 대상2SID)                      # 대상 인스턴스 SID
          )
        )
      
      -- 정적 리스너를 시작하고 상태를 확인합니다. 리스너 이름(LISTENER_DG)을 명시하지 않으면 기본값인 LISTENER를 대상으로 동작하므로, 별도의 리스너 이름을 생성한 경우에는 반드시 해당 이름을 지정해 주어야 합니다.
      $ lsnrctl start LISTENER_DG
      $ lsnrctl status LISTENER_DG
      
      -- ora_pmon_대상#SID 프로세스가 출력되어야 합니다.
      $ ps -elf | grep pmom
      
    4. 인스턴스 기동(oracle 유저): 대상 서버에서 DB를 NOMOUNT 상태로 올립니다. “ORACLE instance started”라는 메시지가 나오면 PFILE 수정이 성공적으로 이루어진 것입니다.
      $ sqlplus / as sysdba
      SQL> STARTUP NOMOUNT PFILE='?/dbs/init<대상SID>.ora';
      
      ---- pfile를 통해 spfile을 생성합니다.
      SQL> CREATE SPFILE FROM PFILE='?/dbs/init<대상SID>.ora';
      
    5. TNS Configuration: 운영 서버와 대상 서버는 tnsnames.ora를 통해 통신이 가능해야 합니다.(tnsping 명령어)
      $ vi $ORACLE_HOME/network/admin/tnsnames.ora (예시)
      CMAIN =
        (DESCRIPTION =
          (ADDRESS = (PROTOCOL = TCP)(HOST = hostname 또는 ip주소)(PORT = 1521))
          (CONNECT_DATA =
            (SERVER = DEDICATED)
            (SERVICE_NAME = CMAIN)
          )
        )
      DR_CMAIN =
        (DESCRIPTION =
          (ADDRESS_LIST =
            (ADDRESS = (PROTOCOL = TCP)(HOST = hostname 또는 ip주소)(PORT = 1581))
          )
          (CONNECT_DATA =
            (SERVER = DEDICATED)
            (SERVICE_NAME = DR_CMAIN)
          )
        )
      
  • RMAN Backup-based Duplication
    1. 백업 파일 전송: 운영 서버의 RMAN 백업 파일과 아카이브 로그를 대상 서버의 동일한 경로로 복사합니다.(NAS를 공유해서 쓴다면 마운트만 하면 됩니다.)
      -- CATALOG START WITH 명령어로 백업 파일의 위치를 인식시켜주는 과정이 필요할 수 있습니다.
      RMAN> CATALOG START WITH '/path/to/backups/';
      
    2. Backup-based Duplication 실행
      -- <New_DB_Name> : 복제가 완료된 후 새롭게 탄생할 데이터베이스의 DB_NAME(ORACLE_SID)
      -- FROM BACKUP 옵션: 기본값이며, 명시적으로 FROM BACKUP을 쓰기도 함
      RMAN> DUPLICATE TARGET DATABASE TO <New_DB_Name> FROM BACKUP LOCATION '/path/to/backups/';
      
  • RMAN Active Database Duplicate
    1. 대상 서버에서 운영 서버로 접속하여 운영 서버에서 대상 서버로 복제할 준비를 합니다.
      $ rman target sys/pass@운영DB auxiliary /
      
    2. Active Database Duplicate 실행
      -- <New_DB_Name> : 복제가 완료된 후 새롭게 탄생할 데이터베이스의 DB_NAME(ORACLE_SID)
      -- FROM ACTIVE DATABASE 옵션: 최신 백업 파일이 없을 때 아주 유용하나 운영 서버에 부하 발생
      RMAN> DUPLICATE TARGET DATABASE TO <New_DB_Name> FROM ACTIVE DATABASE;
      

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다