Cold Backup(닫힌 백업)은 DB를 종료시킨 후(shutdown) 전체 파일들(data file, redo log file, control file, parameter file, password file)을 백업 받는 것입니다.
주의사항은 아래와 같습니다.
1. 모든 파일을 동일한 checkpoint SCN을 가져야 합니다.
2. shutdown immediate
, shutdown transactional
, shutdown normal
과 같이 정상적으로 shutdown되어야만 합니다. 정상적인 종료의 의미는 커밋된 데이터는 저장되고 커밋 되지 않은 데이터는 롤백이 된다는 의미입니다.
3. archive log mode / no archive log mode 모두 사용될 수 있습니다.
4. datafiles, redo log files, control files 모두 백업 받을 수 있습니다.
5. Tablespace를 offline 시켜두고 받는 백업 역시 일종의 닫힌 백업으로 생각할 수 있습니다.
SQL> select name, status from v$datafile;
SQL> select a.group#, a.member, b.bytes/1024/1024 MB, b.archived, b.status
2 from v$logfile a, v$log b
3 where a.group#=b.group#
4 order by 1, 2;
SQL> select name from v$controlfile;
SQL> shutdown immediate;
-- 백업 경로 : /data/backup/close/
SQL> !cp -av <기존 Data File 경로>/*.dbf /data/backup/close/
SQL> !cp -av <기존 Redo Log File 경로>/*.log /data/backup/close/
SQL> !cp -av <기존 Control File 경로>/*.ctl /data/backup/close/
SQL> startup
Hot Backup(열린 백업)은 DB를 중단하지 않은 상태에서 백업을 받는 방법입니다. Cold Backup의 치명적인 단점인 DB를 중단한다는 것을 보완하는 방법인 만큼 백업 과정에서 몇 가지가 추가됩니다.
Hot Backup은 반드시 archive log mode에서 수행해야 합니다. no archive log mode에서 Hot Backup 수행 시 에러가 발생합니다.
Cold Backup은 DB 종료 후 전체 DB를 백업 받는다면, Hot Backup은 Tablespace 단위로 백업을 받습니다. 백업을 받기 전에 해당 Tablespace를 백업 모드로 설정한 후 백업을 수행하고, 백업이 끝나면 백업 모드를 해제합니다.
SQL> alter tablespace khyup begin backup;
SQL> !cp <기존 Data File 경로> /data/backup/open
SQL> alter tablespace khyup end backup;
begin backup
을 수행하면 내부적으로 어떤 일이 일어날까요?
먼저 checkpoint가 발생해 DB Buffer Cache에 있는 해당 Tablespace의 내용이 해당 Data File에 기록됩니다. 그리고 해당 SCN이 Control File과 해당 Data File Header에 기록되며, 해당 Data File Header에는 Hot-backup-in-progress
이라는 플래그값이 표시됩니다. DBWR
은 이 Data File에는 기록된 SCN 이후의 작업은 저장하지 않습니다. 이후의 변경 작업은 모두 Redo Log에 기록했다가 end backup
명령이 수행되면 모두 Data File에 반영하게 됩니다. 이렇게 DB를 중단하지 않고도 일관성을 유지할 수 있습니다. 그래서 먼저 begin backup
명령을 수행한 후 복사를 하는 것입니다.
Hot Backup 동안 DML 작업이 일어나면 많은 양의 Redo Log가 발생하게 될 것이고, 백업이 오래 지속되면 그만큼 Redo Log File에 저장될 내용 역시 많아질 것입니다. 백업이 끝났을 때 그동안의 Redo Log의 내용을 모두 Data File에 적용해야 하기에 모든 기록을 남기기 위해 archive log mode로 동작해야 하는 것입니다.
begin backup
이후 Redo Log에 저장되는 데이터들은 row 단위가 아닌 block 단위로 저장됩니다. 그래서 더더욱 Redo Log의 양이 많아지고 archive log mode가 필요합니다.
end backup
를 수행하면 내부적으로 어떻게 동작할까요?
모든 백업을 마치고 end backup
를 수행하면 해당 Data File에 기록된 마지막 SCN을 시작으로 하는 redo record
를 만듭니다. redo record
를 통해서 백업 도중에 변경된 내용을 Redo Log와 Archive Log에서 찾아서 적용시킨 후 checkpoint를 발생시킵니다.
만약 hot backup 도중 변경 사항이 발생해 redo log에 기록되고 있는 와중에 end backup
명령을 수행하면 redo log로의 마지막 기록을 멈추고 Data File에 checkpoint가 우선적으로 수행됩니다.
Hot Backup을 수행하는 와중에는 shutdown immediate
, shutdown normal
을 수행할 수 없으며, 해당 Tablespace를 offline할 수도 없습니다.
Hot Backup으로 Data File
, Control File
은 백업 받을 수 있으나 보시다시피 Redo Log File
은 사용 중이기에 백업 받을 수 없습니다.
end backup
이 수행되었는지 아닌지 여부는 아래의 쿼리를 통해 조회할 수 있습니다.
SQL> select a.file#, a.name, b.status, to_char(b.time, 'YYYY-MM-DD:HH24:MI:SS') as time
2 from v$datafile a, v$backup b
3 where a.file#=b.file#;
status
부분에 ACTIVE
로 되어 있다면 begin backup
이라는 의미이며, NOT ACTIVE
는 end backup
상태이거나 begin backup
을 수행하지 않았다는 의미입니다. time
부분은 가장 마지막에 begin backup
을 받은 시간을 의미합니다.
Data File
, Control File
을 Hot Backup 받도록 하겠습니다.
(Tablespace를 모두 적어줘야 하기에 번거로운 스크립트입니다. 원리를 파악하도록 합시다)
SQL> !vi /home/oracle/open_backup.sql
conn / as sysdba;
alter tablespace users begin backup;
!cp -av /ORA19/app/oracle/oradata/ORACLE19/users01.dbf /data/backup/open/
alter tablespace users end backup;
alter tablespace sysaux begin backup;
!cp -av /ORA19/app/oracle/oradata/ORACLE19/sysaux01.dbf /data/backup/open/
alter tablespace sysaux end backup;
alter tablespace undotbs1 begin backup;
!cp -av /ORA19/app/oracle/oradata/ORACLE19/undotbs01.dbf /data/backup/open/
alter tablespace undotbs1 end backup;
alter tablespace system begin backup;
!cp -av /ORA19/app/oracle/oradata/ORACLE19/system01.dbf /data/backup/open/
alter tablespace system end backup;
alter tablespace khyup begin backup;
!cp -av /ORA19/app/oracle/oradata/ORACLE19/khyup01.dbf /data/backup/open/
alter tablespace khyup end backup;
alter database backup controlfile to '/data/backup/open/control01.ctl';
:wq!
SQL> @/home/oracle/open_backup.sql
SQL> alter system checkpoint;
다음은 일자별로 자동으로 begin backup을 수행하는 백업 스크립트입니다.
begin_backup.sh
)copy_backup.sh
)end_backup.sh
)-- main_backup.sh
export LANG=C
export ORACLE_BASE=<환경변수 ORACLE_BASE 값>
export ORACLE_HOME=<환경변수 ORACLE_HOME 값>
export PATH=<환경변수 PATH 값>
export ORACLE_SID=<원하는 SID>
touch /home/oracle/total.log
echo ""
echo "set begin backup mode"
time sh /home/oracle/begin_backup.sh >> /home/oracle/total.log
echo ""
echo "end begin backup mode"
echo ""
echo "start file copy..."
time sh /home/oracle/copy_backup.sh >> /home/oracle/total.log
echo "end file copy"
echo ""
echo "set end backup mode"
time sh /home/oracle/end_backup.sh >> /home/oracle/total.log
echo "complete hot backup"
-- 1. begin_backup.sh
export LANG=C
export ORACLE_BASE=<환경변수 ORACLE_BASE 값>
export ORACLE_HOME=<환경변수 ORACLE_HOME 값>
export PATH=<환경변수 PATH 값>
export ORACLE_SID=<원하는 SID>
sqlplus /nolog <<EOF1 -- login 없이 sqlplus 접속
conn / as sysdba
set head off
set feedback off
set time off
set timing off
set echo off
spool /tmp/online.tmp
select 'alter tablespace '|| tablespace_name ||' begin backup;' \
from dba_tablespace \
where status='ONLINE' \
and contents != 'TEMPORARY';
spool off
!cat /tmp/online.tmp | egrep -v spool | egrep -v SQL | egrep -v [2-4] > /home/oracle/begin.sql
@/home/oracle/begin.sql
!sh /home/oracle/status.sh
exit
EOF1
-- 2. copy_backup.sh
export LANG=C
export ORACLE_BASE=<환경변수 ORACLE_BASE 값>
export ORACLE_HOME=<환경변수 ORACLE_HOME 값>
export PATH=<환경변수 PATH 값>
export ORACLE_SID=<원하는 SID>
sqlplus /nolog <<EOF2
conn / as sysdba
set head off
set time off
set timing off
set feedback off
set echo off
set line 200
col name for a100
spool /home/oracle/cp.tmp
select 'mkdir /data/backup/open/'||to_char(sysdate,'YYYY-MM-DD-HH24-MI-SS') from dual;
select 'cp -av '||name||' /data/backup/open/'||to_char(sysdate,'YYYY-MM-DD-HH24-MI-SS') "name" from v\$datafile;
spool off
spool /home/oracle/control.tmp
alter session set nls_date_format='YYYY-MM-DD-HH24-MI-SS';
select 'alter database backup controlfile to ' '/data/backup/open/'||sysdate||'/'||sysdate||'.ctl' ' ; ' from dual;
spool off
!cat /home/oracle/cp.tmp | egrep -v SQL > /home/oracle/cp.sh
!cat /home/oracle/control.tmp | egrep -v SQL > /home/oracle/control.sql
!sh /home/oracle/cp.sh
@/home/oracle/control.sql
exit
EOF2
-- 3. end_backup.sh
export LANG=C
export ORACLE_BASE=<환경변수 ORACLE_BASE 값>
export ORACLE_HOME=<환경변수 ORACLE_HOME 값>
export PATH=<환경변수 PATH 값>
export ORACLE_SID=<원하는 SID>
sqlplus /nolog <<EOF3
conn / as sysdba
set head off
set feedback off
set time off
set timing off
set echo off
spool /tmp/online.tmp
select 'alter tablespace '|| tablespace_name || ' end backup;' \
from dba_tablespace \
where status='ONLINE' \
and contents != 'TEMPORARY';
spool off
!cat /tmp/online.tmp | egrep -v spool | egrep -v SQL | egrep -v [2-4] > /home/oracle/end.sh
@/home/oracle/end.sql
!sh /home/oracle/status.sh
exit
EOF3
-- 4. status.sh
export LANG=C
export ORACLE_BASE=<환경변수 ORACLE_BASE 값>
export ORACLE_HOME=<환경변수 ORACLE_HOME 값>
export PATH=<환경변수 PATH 값>
export ORACLE_SID=<원하는 SID>
sqlplus /nolog <<EOF4
conn / as sysdba
set head on
set echo off
set feedback off
spool /tmp/status.tmp
set line 200
col name for a50
col status for a15
select a.file#, a.name, b.status, to_char(b.time,'YYYY-MM-DD-HH24-MI-SS') "Time" \
from v\$datafile a, v\$backup b \
where a.file#=a.file#;
spool off
exit
EOF4
$ sh main_backup.sh
이 스크립트 파일을 crontab
에 등록해 두면 아주 쉽게 주기적으로 백업을 수행할 수 있습니다.
참고
정리 감사합니다