[Oracle] RMAN으로 백업 및 복구하기
예전 글에서는 Oracle Data Pump 유틸리티(expdp/impdp)를 사용하여 스키마를 이전하는 절차를 알아봤는데요, 이번 글에서는 RMAN으로 Oracle Database를 백업 및 복구하늕 절차를 정리해 보고자 합니다. 아직까지 백업/복구 모의훈련을 위한 가상서버(VM)가 준비되지 않아서 먼저 정리를 하고, VM이 준비되면 모의훈련을 하면서 부족한 부분을 보충해 나갈 예정입니다. 모의훈련이 끝나면 백업/복구 절차가 검증되었다고 이 글에 남기도록 하겠습니다. 혹시 전문DBA께서 이 글을 보셨다면 부족한 부분에 많은 의견부탁드립니다.
- RMAN 환경 구성 및 기본 사용법 알아보기
- RMAN으로 백업하기
- RMAN으로 복구하기
- 전체 복구하기
- 특정 데이터파일만 복구하기
- 다른 디스크에 복구하기
- 다른 데이터베이스 서버에 복구하기(복제 및 이관)
1. RMAN 환경 구성 및 기본 사용법 알아보기
- SID 확인: $ORACLE_SID는 v$instance 뷰를 통해 확인합니다.
SQL> SELECT instance_name AS 운영SID FROM v$instance;
- 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
- Retention Policy 설정: 백업본을 며칠간 보관할지 결정하세요. (예: 7일)
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;
- Controlfile Autobackup: DB 구조 변경 시 백업이 자동 생성되도록 설정하세요.
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
- 병렬 처리(PARALLELISM) 설정: 채널을 2개 할당하여 백업 속도를 높이면서도 서비스 부하를 고려합니다.
RMAN> show device type; 명령으로 병렬 처리 채널를 확인할 수 있습니다.RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 2;
- 백업 효율 극대화: 동일한 읽기 전용(Read-Only) 테이블스페이스나 이미 백업된 아카이브 로그 등을 지능적으로 제외하므로, 특히 매일 아카이브 로그를 백업하는 환경에서 불필요한 I/O를 획기적으로 줄여줍니다.
RMAN> CONFIGURE BACKUP OPTIMIZATION ON;
2. RMAN으로 백업하기
- 아래 스크립트는 증분백업(Incremental backup) 전략을 사용합니다. 일요일은 풀백업, 월요일~토요일에는 증분백업 전략으로 구성하였습니다.
#!/bin/bash # ======================================================== # Script File Name: integrated_rman_backup.sh # Purpose : Automated Incremental Backup (Sun:Full, Mon~Sat:Incremental) # ======================================================== # 1. Environment Configuration export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/11.2.0.4/dbhome_1/ export ORACLE_SID=CMAIN_2 export PATH=$ORACLE_HOME/bin:$PATH export BASE_PATH=$(cd "$(dirname "$0")" && pwd) export BACKUP_ROOT="/nas/backup/orabackup/$ORACLE_SID" export DATE_DIR=$(date +%Y-%m-%d) export FULL_PATH="$BACKUP_ROOT/$DATE_DIR" export LOG_FILE="${BASE_PATH}/rman_backup_total.log" # Weekday (1:Mon, ..., 7:Sun) DAY_OF_WEEK=$(date +%u) # Sun: Full Backup, Mon~Sat: Incremental Backup # %d: Database Name # %U: Unique Identifier created by system if [ $DAY_OF_WEEK -eq 7 ]; then BACKUP_CMD="BACKUP INCREMENTAL LEVEL 0 DATABASE FORMAT '$FULL_PATH/L0_%d_%U' TAG 'WEEKLY_FULL_L0';" MODE="Full(L0)" else BACKUP_CMD="BACKUP INCREMENTAL LEVEL 1 DATABASE FORMAT '$FULL_PATH/L1_%d_%U' TAG 'DAILY_INCR_L1';" MODE="Incr(L1)" fi mkdir -p $FULL_PATH echo "=========================================================" >> $LOG_FILE echo "--- Backup Started at $(date '+%Y-%m-%d %H:%M:%S') ---" >> $LOG_FILE echo "--- Mode: $MODE ---" >> $LOG_FILE # 2. RMAN Execution rman target / <> $LOG_FILE # [운영 최적화 설정] : RMAN 기본 운영환경 변경 #CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS; #CONFIGURE CONTROLFILE AUTOBACKUP ON; #CONFIGURE DEVICE TYPE DISK PARALLELISM 2; #CONFIGURE BACKUP OPTIMIZATION ON; # [상태 점검] CROSSCHECK BACKUP; CROSSCHECK ARCHIVELOG ALL; CROSSCHECK COPY OF CONTROLFILE; # [백업 실행] 쉘 변수로 전달받은 명령 실행 # FORMAT : 백업파일 저장 경로 설정 # DELETE INPUT : 아카이브 로그를 백업 세트 안에 포함시킨 후 원본을 자동 삭제 RUN { $BACKUP_CMD BACKUP ARCHIVELOG ALL FORMAT '$FULL_PATH/ARC_%d_%U' DELETE INPUT; } # [사후 정리] DELETE NOPROMPT EXPIRED BACKUP; DELETE NOPROMPT EXPIRED ARCHIVELOG ALL; DELETE NOPROMPT EXPIRED COPY OF CONTROLFILE; REPORT OBSOLETE; DELETE NOPROMPT OBSOLETE; # [15일 경과 강제 삭제] RETENTION POLICY에도 불구하고 삭제되지 않는 데이터파일 삭제 DELETE NOPROMPT BACKUP COMPLETED BEFORE 'sysdate - 15'; DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'sysdate - 15'; EXIT; EOF echo "--- Backup Finished at $(date '+%Y-%m-%d %H:%M:%S') ---" >> $LOG_FILE echo "=========================================================" >> $LOG_FILE - crontab에 등록하여 매일 자동으로 실행합니다.
- 직접 위 백업 스크립트를 실행했다면 아래 쿼리를 통해 현재 병렬로 작동 중인 채널의 수를 확인할 수 있습니다.
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;
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): 다른 서버에 복구하기 위해서는 환경 설정이 가장 중요합니다.
- 비밀번호 파일 동기화: 운영 서버의 비밀번호 파일을 복사한 후 이름을 변경하여 사용할 수 있으나($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
- 환경 파일 설정 (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=
- 정적 리스너 등록(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 - 인스턴스 기동(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';
- 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) ) )
- 비밀번호 파일 동기화: 운영 서버의 비밀번호 파일을 복사한 후 이름을 변경하여 사용할 수 있으나($ORACLE_HOME/dbs/orapw<SID>), orapwd 명령어를 사용해서 새 비밀번호 파일을 생성하는 것을 추천합니다.
- RMAN Backup-based Duplication
- 백업 파일 전송: 운영 서버의 RMAN 백업 파일과 아카이브 로그를 대상 서버의 동일한 경로로 복사합니다.(NAS를 공유해서 쓴다면 마운트만 하면 됩니다.)
-- CATALOG START WITH 명령어로 백업 파일의 위치를 인식시켜주는 과정이 필요할 수 있습니다. RMAN> CATALOG START WITH '/path/to/backups/';
- 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 백업 파일과 아카이브 로그를 대상 서버의 동일한 경로로 복사합니다.(NAS를 공유해서 쓴다면 마운트만 하면 됩니다.)
- RMAN Active Database Duplicate
- 대상 서버에서 운영 서버로 접속하여 운영 서버에서 대상 서버로 복제할 준비를 합니다.
$ rman target sys/pass@운영DB auxiliary /
- Active Database Duplicate 실행
-- <New_DB_Name> : 복제가 완료된 후 새롭게 탄생할 데이터베이스의 DB_NAME(ORACLE_SID) -- FROM ACTIVE DATABASE 옵션: 최신 백업 파일이 없을 때 아주 유용하나 운영 서버에 부하 발생 RMAN> DUPLICATE TARGET DATABASE TO <New_DB_Name> FROM ACTIVE DATABASE;
- 대상 서버에서 운영 서버로 접속하여 운영 서버에서 대상 서버로 복제할 준비를 합니다.
