2012年4月17日 星期二

第二十二回 Oracle DB Online Backup 到其他主機

建立 DataGuard 時就必須複製整套 DB 資料,有人是使用 RMAN Duplicate 來做,我是不習慣用啦,因為前置還得搞通 TNS 那些東西,還必須確保備份也是正常的,所以就直接從 Source Database 複製是最快的。只是會消耗一點 Production 主機的效能和網路頻寬。而且這個方法只要 RSH 或 SSH 有 Trust 設過就可以使用。

測試過 400GB 資料在 1000Mbps 網路下,只需要 2 小時不到就可以完成了。如果你是要即時備份,當然是 Disk 快照最方便的。因為透過我這個方法,你還必須確保複製過程的 Archivelog 都必須存在,事後還需要做 Recovery 。這也算是窮人的 snapshot 吧。只是人家 snapshot 是以秒在算,這個可能都要幾個小時起跳。

首先一般資料庫在規畫時都會將 Datafile 放在特定目錄,所以在 Remote 端 Create Filesystem 時大部份人只會開一層,然後 Datafile 就放在下面,但有些套裝軟體比較雞婆(像SAP),每個 datafile 在 create 時會再建一層目錄,因此用 Scripts 做時就將這個因素也考慮進去,所有關聯目錄會依 Source 端也一併建好,如果用 RMAN 做的話,沒將整個目錄結構設對的話是倒不回來的。

整個 Scripts 內容如下:

#!/usr/bin/ksh

#===================================================================================
# 平常不使用時可將 exit 註解拿掉,以免誤執行此 Scripts,蓋到你的 Target 端資料庫
#exit
#===================================================================================

#參數初始
export ORACLE_SID=DB1
workdir="/orahome/jobs/dbdr"
target_dir=""
target_system="db_host_target"
remote_cmd=rsh
run_date=`date +%m%d`
logfile="/orahome/jobs/logs/dg_init$ORACLE_SID.log.$run_date"

#切換 SSH 或 RSH 用的 copy 工具,配合上面 remote_cmd 參數
case $remote_cmd in
rsh)
copy_method=rcp
break
;;
ssh)
copy_method=scp
break
;;
esac

date > $logfile

#先抓 Tablespace 名稱
echo "get Tablespace information...." >> $logfile
cd $workdir
echo "set term off" >$workdir/get_tablespace_name.sql
echo "set pagesize 60" >$workdir/get_tablespace_name.sql
echo "set head off" >>$workdir/get_tablespace_name.sql
echo "set feedback off" >>$workdir/get_tablespace_name.sql
echo "spool $workdir/tablespace.lst" >>$workdir/get_tablespace_name.sql
echo "select name from v\$tablespace where name not in (select distinct tablespace_name from dba_temp_files);" >>$workdir/ge
t_tablespace_name.sql
echo "spool off" >>$workdir/get_tablespace_name.sql
echo "exit" >>$workdir/get_tablespace_name.sql
sqlplus "/ as sysdba" @$workdir/get_tablespace_name.sql

#切換 Backup Mode 後抓出每個 Tablespace 內置的 Datafile ,開始複製到遠端
for i in `cat $workdir/tablespace.lst`
do
get_datafile="$workdir/get_datafile_name.sql"
echo " " >> $logfile
echo "==============================================================" >> $logfile
date >> $logfile
echo "$i transfer to backup mode" >> $logfile
echo "" > $get_datafile
#echo "select ts# from v\$tablespace where name = '$i';" >> $get_datafile
echo "alter tablespace $i begin backup;" >> $get_datafile
echo "set linesize 120" >> $get_datafile
echo "set pagesize 200" >> $get_datafile
echo "set term off" >> $get_datafile
echo "set head off" >> $get_datafile
echo "set feedback off" >> $get_datafile
echo "spool $workdir/ora_datafile_$i.lst" >> $get_datafile
echo "select name from v\$datafile where ts#=( select ts# from v\$tablespace where name = '$i');" >>$get_datafile
echo "spool off" >>$get_datafile
echo "exit" >>$get_datafile
sqlplus "/ as sysdba" @get_datafile_name.sql

for list in `cat $workdir/ora_datafile_$i.lst`
do

target_dir=`dirname $list`

result=$(rsh $target_system "test -d ${target_dir};echo \$?")

if [ result -ne 0 ] ; then
echo "create `dirname $list` on target filesystem..." >> $logfile
$remote_cmd $target_system mkdir -p $target_dir
fi

echo "copy $list to target filesystem..." >> $logfile
$copy_method $list $target_system:$target_dir
done

echo "alter tablespace $i end backup;" > $get_datafile
echo "exit" >>$get_datafile
sqlplus "/ as sysdba" @get_datafile_name.sql
echo "$i tablespace transfer complete" >> $logfile
echo "$i transfer to online mode" >> $logfile
date >> $logfile
echo "==============================================================" >> $logfile
echo " " >> $logfile
done

# Datafile 全部傳完後,寫個 LOG
echo "database transfer complete...." >> $logfile

#接下來是 online redo log
echo "==============================================================" >> $logfile
echo "set linesize 120" >> $get_datafile
echo "set pagesize 200" >> $get_datafile
echo "set term off" >> $get_datafile
echo "set head off" >> $get_datafile
echo "set feedback off" >> $get_datafile
echo "spool $workdir/ora_datafile.lst" >> $get_datafile
echo "select member from v\$logfile;" >>$get_datafile
echo "spool off" >>$get_datafile
echo "exit" >>$get_datafile
sqlplus "/ as sysdba" @get_datafile_name.sql

for list in `cat $workdir/ora_datafile.lst`
do

target_dir=`dirname $list`

result=$(rsh $target_system "test -d ${target_dir};echo \$?")

if [ result -ne 0 ] ; then
echo "create `dirname $list` for online REDO Log on target filesystem..." >> $logfile
$remote_cmd $target_system mkdir -p $target_dir
fi

done

# 最後是 Controlfile ,會直接複製到 Remote 端的對應位置,所以 Memory 配置夠的話,直接啟動就是
# standby database mode了。就可以開始 Dataguard 設定。

echo "backup controlfile transfer...." >> $logfile
echo "alter database create standby controlfile as '$workdir/ctrlf_bk_$run_date';" > $get_datafile
echo "exit" >>$get_datafile
sqlplus "/ as sysdba" @$get_datafile
echo "set linesize 120" > $get_datafile
echo "set pagesize 200" >> $get_datafile
echo "set term off" >> $get_datafile
echo "set head off" >> $get_datafile
echo "set feedback off" >> $get_datafile
echo "spool $workdir/ora_datafile.lst" >> $get_datafile
echo "select name from v\$controlfile;" >>$get_datafile
echo "spool off" >>$get_datafile
echo "exit" >>$get_datafile
sqlplus "/ as sysdba" @$get_datafile

for list in `cat $workdir/ora_datafile.lst`

do
target_dir=`dirname $list`
result=$(rsh $target_system "test -d ${target_dir};echo \$?")
if [ result -ne 0 ] ; then
echo "create `dirname $list` for Controlfile file on target filesystem..." >> $logfile
$remote_cmd $target_system mkdir -p $target_dir
fi
#echo $target_dir
#echo $list
$copy_method $workdir/ctrlf_bk_$run_date $target_system:$list
done

rm $workdir/ctrlf_bk_$run_date
echo "backup controlfile transfer complete...." >> $logfile
echo "==============================================================" >> $logfile


缺點及注意事項
1. 前置處理 SSH 和 RSH 必須設定完成可不需密碼 Remote Login 到遠端。
2. Orache Home ,這個當然要自己裝嘍,不然設法 Copy 過去改,就不多寫了,因為這個東西也不是每次必 Copy 的
3. Initial File 和 SPFILE當然還是得自己先手動設置,只要複製過去就可以了
4. Archive Log 的部份,因為這隻是為了 Dataguard 做的,事後本來就會去設定傳遞 Archive Log
所以就沒雞婆繼續改下去
5. Temp File 沒有特別去處理,Target 端啟動後,要自行重新建立 Temp File
6. 兩邊的 shell 必須是 sh 或 ksh ,如果像 SAP 預設是使用 csh ,請先更改 default shell ,不然不能正常執行
7. 請測試過再用正式環境來玩,搞錯自己把自己的檔案蓋掉,不負任何責任。
8. 這個只是為了有需求一次複製整個資料庫使用(如軟體上線前或需要一個環境測試,又沒有 Disk snapshot 的功能時),不是為了平常備份做的,真的日常備份請用磁帶機。除非你覺得硬碟太便宜。