建立 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 的功能時),不是為了平常備份做的,真的日常備份請用磁帶機。除非你覺得硬碟太便宜。
2012年4月17日 星期二
2011年11月15日 星期二
第二十一回 AIX + Oracle 10gR4 & 10gR5 使用 LOCK_SGA 不使用 large page 的方法
最近一個系統一直有 page swap 的問題,雖然系統發生 page swap 就代表平常記憶體不足,或是程式異常佔用記憶體,但這台機器其實己經沒有 Memory 可增加了,僅剩的方法就是請 AP 人員 Tunning 程式,分散系統 Loading 。
但是其實 Oracle Database 的系統中,SGA 的資源如果發生 Swap 的狀況下,系統會跟當掉一樣,少則幾分鐘,重至系統會整個癱瘓,最後只好重啟系統。從前一直以來為了預防這件事,在 Memory 非常大的系統上,會建議客戶將作業系統下,vmo 的參數 v_pinshm=1 設上,再配合 ORACLE LOCK_SGA=true ,將 SGA pin 在記憶體中,如此 SGA 就不會再被 swap。 之前第七回有說明過這件事 http://it2man.blogspot.com/2010/05/aix.html
但 Oracle 在 10.2.0.4 後,規則有些改變,系統會需要你設定 Large Page ,再配合作業系統調整 Oracle User 的權限,才能進行 Lock_sga ,不然在啟動時會發生錯誤。
詳細請見 metalink How to enable Large Page Feature on AIX-Based Systems [ID 372157.1]
這邊節錄幾個重點
一、須在 root 下將 oracle 授予權限
chuser capabilities=CAP_BYPASS_RAC_VMM,CAP_PROPAGATE oracle
二、計算 Large Page 之大小,公式如下,以每個 Large Page 為 16MB 計算,取得要佔用的數目
num_of_large_pages = INT((total_SGA_size-1)/16MB)+1
三、VMO 設定之參數需將重點二計算出來的數目及 lgpg_size=16777216 (16MB) 和一開始說明的 v_pinshm=1 也設上
vmo -p -o lgpg_regions=num_of_large_pages -o lgpg_size=16777216
vmo -p -o v_pinshm=1 (請注意,我記得這個參數要重啟才會生效)
四、spfile 裏需設定 lock_sga=true
五、最重要的一點,這篇 Metalink 有 Bug ,寫在最後面,上述四點都做到後,SGA 是 pin 不到你預先規畫好的記憶體內的,他會另外自己再要一塊空間,需要配合最後寫的 NOTE:728444.1 中所述的 Patch 安裝後才會真的去使用你己經幫 Oracle 設定好的空間。10.2.0.4 和 10.2.0.5 都有這個 Bug。不過後來我用別的方法,沒有去上這個 Fix ,所以還沒測試過。
上面寫的,都不是本篇標題所要做的,最後來說明標題的作業內容
雖然官方有說使用 Large Page 會增進 5% 左右的效能,但是會造成每次重開機時間比較久,每次要重新設定 SGA Size 就需要在作業系統事先分配等缺點。所以還是有原來不需要設定和計算 Large Page 就可以 Pin 的方式。
重點在部驟一:
chuser capabilities=CAP_NUMA_ATTACH,CAP_BYPASS_RAC_VMM,CAP_PROPAGATE oracle
是的,只要授予作業系統 User 權限時,增加capabilities=CAP_NUMA_ATTACH 即可
第三個部驟的 vmo -p -o lgpg_regions=num_of_large_pages -o lgpg_size=16777216 就不用再設定了,直接就可以做 pin 的動作,當然 v_pinshm=1 是一定要設的
當然最後要說明一下,這個設定動作我好像在 Metalink 找不到,所以有可能你日後遇到問題時,跟 Oracle 諮詢的話,這個 support 看到你的設定方式不同,他可能會先要求你修正。
但是其實 Oracle Database 的系統中,SGA 的資源如果發生 Swap 的狀況下,系統會跟當掉一樣,少則幾分鐘,重至系統會整個癱瘓,最後只好重啟系統。從前一直以來為了預防這件事,在 Memory 非常大的系統上,會建議客戶將作業系統下,vmo 的參數 v_pinshm=1 設上,再配合 ORACLE LOCK_SGA=true ,將 SGA pin 在記憶體中,如此 SGA 就不會再被 swap。 之前第七回有說明過這件事 http://it2man.blogspot.com/2010/05/aix.html
但 Oracle 在 10.2.0.4 後,規則有些改變,系統會需要你設定 Large Page ,再配合作業系統調整 Oracle User 的權限,才能進行 Lock_sga ,不然在啟動時會發生錯誤。
詳細請見 metalink How to enable Large Page Feature on AIX-Based Systems [ID 372157.1]
這邊節錄幾個重點
一、須在 root 下將 oracle 授予權限
chuser capabilities=CAP_BYPASS_RAC_VMM,CAP_PROPAGATE oracle
二、計算 Large Page 之大小,公式如下,以每個 Large Page 為 16MB 計算,取得要佔用的數目
num_of_large_pages = INT((total_SGA_size-1)/16MB)+1
三、VMO 設定之參數需將重點二計算出來的數目及 lgpg_size=16777216 (16MB) 和一開始說明的 v_pinshm=1 也設上
vmo -p -o lgpg_regions=num_of_large_pages -o lgpg_size=16777216
vmo -p -o v_pinshm=1 (請注意,我記得這個參數要重啟才會生效)
四、spfile 裏需設定 lock_sga=true
五、最重要的一點,這篇 Metalink 有 Bug ,寫在最後面,上述四點都做到後,SGA 是 pin 不到你預先規畫好的記憶體內的,他會另外自己再要一塊空間,需要配合最後寫的 NOTE:728444.1 中所述的 Patch 安裝後才會真的去使用你己經幫 Oracle 設定好的空間。10.2.0.4 和 10.2.0.5 都有這個 Bug。不過後來我用別的方法,沒有去上這個 Fix ,所以還沒測試過。
上面寫的,都不是本篇標題所要做的,最後來說明標題的作業內容
雖然官方有說使用 Large Page 會增進 5% 左右的效能,但是會造成每次重開機時間比較久,每次要重新設定 SGA Size 就需要在作業系統事先分配等缺點。所以還是有原來不需要設定和計算 Large Page 就可以 Pin 的方式。
重點在部驟一:
chuser capabilities=CAP_NUMA_ATTACH,CAP_BYPASS_RAC_VMM,CAP_PROPAGATE oracle
是的,只要授予作業系統 User 權限時,增加capabilities=CAP_NUMA_ATTACH 即可
第三個部驟的 vmo -p -o lgpg_regions=num_of_large_pages -o lgpg_size=16777216 就不用再設定了,直接就可以做 pin 的動作,當然 v_pinshm=1 是一定要設的
當然最後要說明一下,這個設定動作我好像在 Metalink 找不到,所以有可能你日後遇到問題時,跟 Oracle 諮詢的話,這個 support 看到你的設定方式不同,他可能會先要求你修正。
2011年9月4日 星期日
聽我在放屁 CASE4 如果 Google 的免費服務當掉一天
如果....這是如果,如果有一天,Google 的雲端服務當掉一天,且不知何時才會修復....
搜尋引擎方面雖然有很多替代品,但並不保證可以很快的幫你找到對的答案.....但是日子還是能過....
地圖服務的話,我也不知道現在人到底有多依賴 Google Map,反正找路的話是方向感比較重要,而且記得一點,路長在嘴上,路人都是你的地圖。
Gmail 沒有備份同步在自己 PC 上的人就比較慘,如果臨時要找一封重要的 Mail ,抱歉沒有....請祈禱官方會早一點修好....
反正生命自己會找出路,如果 Internet 還能聯網的話,不至於什麼都不能做,只是對一般像我這種 IT 人員的話,平常找解決方案用慣 Google 了,大概會像斷手斷腳一樣吧。
我想未來可能會有一天無 Google 日或一天無網日,畢竟現代人出門都被網路綁住了,雖然說真的很方便....
我想網路再怎麼依賴也不會像空氣和水一樣需要,所以有時還是不要帶任何可以連網的東西出門去看看,其實也不會怎樣的.....
只是像我們這種 IT 奴工,當 Vendor 時是被客戶 Call ,到 User Site ,設備都設定了 Alarm ,有事設備會直接發簡訊 Call 你,我想除非出國到一個電話接不到的地方,不然大概也沒辦法不帶電話吧。
搜尋引擎方面雖然有很多替代品,但並不保證可以很快的幫你找到對的答案.....但是日子還是能過....
地圖服務的話,我也不知道現在人到底有多依賴 Google Map,反正找路的話是方向感比較重要,而且記得一點,路長在嘴上,路人都是你的地圖。
Gmail 沒有備份同步在自己 PC 上的人就比較慘,如果臨時要找一封重要的 Mail ,抱歉沒有....請祈禱官方會早一點修好....
反正生命自己會找出路,如果 Internet 還能聯網的話,不至於什麼都不能做,只是對一般像我這種 IT 人員的話,平常找解決方案用慣 Google 了,大概會像斷手斷腳一樣吧。
我想未來可能會有一天無 Google 日或一天無網日,畢竟現代人出門都被網路綁住了,雖然說真的很方便....
我想網路再怎麼依賴也不會像空氣和水一樣需要,所以有時還是不要帶任何可以連網的東西出門去看看,其實也不會怎樣的.....
只是像我們這種 IT 奴工,當 Vendor 時是被客戶 Call ,到 User Site ,設備都設定了 Alarm ,有事設備會直接發簡訊 Call 你,我想除非出國到一個電話接不到的地方,不然大概也沒辦法不帶電話吧。
2011年8月9日 星期二
第二十回 RMAN Restore 及 BRRESTORE 筆記
最近記性愈來愈差,做過的事,大約過一個月就不記得了,昨天分別用 RMAN 及 BRRESTORE 還原 SAP 的資料庫,趕緊筆記一下。
我這台 AIX 5.3 上面安裝SAP Netweaver 使用的備份是 EMC Networker 這套備份軟體,安裝了 LGTO 的 Agent 及 SAP Module.
# lslpp -l|grep LG
LGTOnmsap.rte 3.5.0.0 COMMITTED EMC NetWorker Module for SAP
LGTOnw.clnt.rte 7.4.1.0 COMMITTED NetWorker Client
如果要做異機還原時,需要在異機安裝上述的 Package ,如果作業系統是用 mksysb Backup/Restore ,就不需再安裝,如果是全新安裝的 Oracle ,就必需安裝,我測試過,可以在只有安裝 Oracle Database 的環境下,將 SAP 的備份還原。
另外 SAP 環境是否能使用 RMAN 還原,備份的方法是關鍵,如果是在 TSM 之下,小弟之前設定的案例都是使用 dd ,這是一種 hot backup 的方式,此時就只能用 brrestore 來還原,只能說透過 RMAN 呼叫時,在還原時又增加了一些靈活度。
務必記得安裝過 Oracle Agent 後, Link Library 是絕對必須的,10G 後做這個動作好像不需重啟資料庫,不過反正這是異機測試機,我還是重啟了。
在下列 Folder 必須存在這個 Link
# pwd
$ORACLE_HOME/lib
#ls -al libobk.a
lrwxrwxrwx 1 oracle dba 22 Feb 17 2009 libobk.a -> /usr/lib/libnworasap.a
另外要異機還原,必須要將 Netwoker 上的 Client 允許其他機器 Restore Backup Set 的權限開啟,另為要被 Restore 的 Node 必須記得在 Networker 上建立 Client 註冊的資訊。
如果順利的話,這時就能使用 RMAN 來還原了
如果 spfile 及 pfile 沒帶過來,可以先使用 startup mount force ,強制啟動資料庫,然後去原資料庫查詢 DBID ,之後還原 Control File ,這邊我是用原機下 Alter database backup 產生的,因為我懶得等磁帶找來找去的。
因為你必須事先查出 controlfile piece 在哪,如果 catalog 還在,當然找的到,如果一個都沒有,頭就比較大了。知道 Backup piece 名字時 Restore Control File 的指令如下。
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
restore controlfile to '/tmp/controlfile.bak' from 'P03_begnclcm.11862_1';release channel c1;
}
Control File 還原後,即可啟動資料庫至 Mount,不過還是先將原機的 SPFILE 備份過來後改為 INIT File ,修改一下相關的 PATH ,再重新啟動資料庫。開始 Restore Datafile
因為這是一個 Netweaver 的平台,所以 Datafile 的 Layout 和正統 R/3 不同,而我因為是做 SAP 單純還原至 Oracle ,所以有些 Folder Name 被我變更了,所公必須下 set newname 變更。
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
set newname for DATAFILE 1 to '/oradata1/P03/system_1/system.data1' ;
set newname for DATAFILE 2 to '/oradata1/P03/undo_1/undo.data1';
set newname for DATAFILE 3 to '/oradata1/P03/sysaux_1/sysaux.data1';
set newname for DATAFILE 4 to '/oradata1/P03/saux_1/saux.data1';
set newname for DATAFILE 5 to '/oradata1/P03/sr3db_1/sr3db.data1';
set newname for DATAFILE 6 to '/oradata1/P03/sr3db_2/sr3db.data2';
set newname for DATAFILE 7 to '/oradata1/P03/sr3db_3/sr3db.data3';
restore database;
release channel c1;
}
接下來我去 SAP Backup Log 查了需要的 Archive Log Range 為 4199 至 4246,依下列指令還原 Archive Log
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
RESTORE ARCHIVELOG FROM SEQ 4199 UNTIL SEQ 4246;
release channel c1;
}
到此為止,應該可以啟動資料庫了吧,結果上面兩個還原沒一個成功
理論上是 OK 的,但在 Networker 這個產品之下,我們的 Resource 不足,只有兩個 Driver ,同時運行了 D2D2T ,而 Netwoker 在做 Data Staging 時,Source 和 Target 兩份資料都會鎖住不讓你存取,所以我下了兩個 RMAN 的指令,經過漫常的等待,完全沒有回應,直到 Data Staging 做完後,終於開始從磁帶讀到資料了。
但是,有部份資料需要換帶,結果 Driver 在換帶過程又被別人搶去用了,以我所知,NBU 可以在 JOB 上設定 Priority ,TSM 的 Restore JOB Priority 是最高的,所以不太會有這類狀況發生。
我花了一天的時間,倒不回這個 Netweaver 30G 的資料,後來心想,才 30G ,幹麼不直接備份下來到 Networker 後,趁他未做 Data Staging 時趕緊 Restore ,不就直接還原了嗎?
結果我重做了一次備份,不到半小時,就將資料庫 Clone 一份出來了,真不知浪費一天時間在幹麼?
另一個小插曲,熟 Oracle 的人可能會問:「為何不用 alter database begin backup ,然後用 Hot Copy 就好了?」
因為這一個 Database 是 SAP ,當初 SAP 初始安裝會設定一個參數 filesystemio_options ,請看 這邊有解釋,而我並未去調整為asynch ( Oracle Default) 所以在此條件下, Hot Backup 是不允許的,只能經由 RMAN 操作這個資料庫。
最後調整完成後,我也覺得很煩,還是乾脆將原機 OS 備份下來後,還原至另一台,改用 brrestore 來做。
假設相關參數檔都在的狀況下,只需 Restore Control file , Data File 及 Archive Log File ,所以只需下三個指令
brrestore -m 0 <-- 還原 Control File ,他會依照 Init File 內定義的 Control File 位置進行複蓋的動作。
上述指令完成後,啟動資料庫至 Mount ,才能繼續下列動作。
brrestore -m full <-- 還原 Datafile ,此指令會直接還原最後一份備份成功的資料
brrestore -b bcnmhluz.aft -m full <-- 假設你知道要還原的 Backup Log 的 File Name ,可以使用 -b 參數指定, brrestore 會找出這份 Backup Set ,並還原回來。
brrestore -a 4199-4246 還原 archive log 中 sequence 為 4199 ~ 4246 的 Log File
如果相關參數檔都不在的話,就比較麻煩,還是使用原來 RMAN 的方式來做比較方便,由 Oracle 幫你找,不過前題是你倒的出 Control File ,能抓到最後一份 Catalog 。
brrestore 的方法至少要有 SAP 存在於 oracle 目錄下的 sapbackup 及 saparch 這兩個 folder 的相關檔案資訊(summary log 及 backup log) ,還有 Oracle HOME 目錄中 dbs 下的 init[Instance Name].sap 及init[Instance Name].utl 這些檔案才能無誤的運作,當然這些東西是可以用 brrestore 倒出來的,不過等我下次有機會做後再上來補完。這些動作之前也常作,不過不是很清楚了。
SAP help 裏的作法是如此的,有機會再來做一次,因為白天我們的 Networker 都在做 Staging ,又沒機會試了。
我只記得 sapdba 實在是比現在的 brtools 好用多了,不知 SAP 在想什麼。
2012/0622 實際操作了一次 Windows 下的 Brrestore ,狀態跟 UNIX 下的不太一樣,好像在過程中的 Log 是不會作動的。可能要 Restore 完成才會有 Log ,不過也可能跟使用的 Backup API 有關,等 Restore 完成再來確認。
我這台 AIX 5.3 上面安裝SAP Netweaver 使用的備份是 EMC Networker 這套備份軟體,安裝了 LGTO 的 Agent 及 SAP Module.
# lslpp -l|grep LG
LGTOnmsap.rte 3.5.0.0 COMMITTED EMC NetWorker Module for SAP
LGTOnw.clnt.rte 7.4.1.0 COMMITTED NetWorker Client
如果要做異機還原時,需要在異機安裝上述的 Package ,如果作業系統是用 mksysb Backup/Restore ,就不需再安裝,如果是全新安裝的 Oracle ,就必需安裝,我測試過,可以在只有安裝 Oracle Database 的環境下,將 SAP 的備份還原。
另外 SAP 環境是否能使用 RMAN 還原,備份的方法是關鍵,如果是在 TSM 之下,小弟之前設定的案例都是使用 dd ,這是一種 hot backup 的方式,此時就只能用 brrestore 來還原,只能說透過 RMAN 呼叫時,在還原時又增加了一些靈活度。
務必記得安裝過 Oracle Agent 後, Link Library 是絕對必須的,10G 後做這個動作好像不需重啟資料庫,不過反正這是異機測試機,我還是重啟了。
在下列 Folder 必須存在這個 Link
# pwd
$ORACLE_HOME/lib
#ls -al libobk.a
lrwxrwxrwx 1 oracle dba 22 Feb 17 2009 libobk.a -> /usr/lib/libnworasap.a
另外要異機還原,必須要將 Netwoker 上的 Client 允許其他機器 Restore Backup Set 的權限開啟,另為要被 Restore 的 Node 必須記得在 Networker 上建立 Client 註冊的資訊。
如果順利的話,這時就能使用 RMAN 來還原了
如果 spfile 及 pfile 沒帶過來,可以先使用 startup mount force ,強制啟動資料庫,然後去原資料庫查詢 DBID ,之後還原 Control File ,這邊我是用原機下 Alter database backup 產生的,因為我懶得等磁帶找來找去的。
因為你必須事先查出 controlfile piece 在哪,如果 catalog 還在,當然找的到,如果一個都沒有,頭就比較大了。知道 Backup piece 名字時 Restore Control File 的指令如下。
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
restore controlfile to '/tmp/controlfile.bak' from 'P03_begnclcm.11862_1';release channel c1;
}
Control File 還原後,即可啟動資料庫至 Mount,不過還是先將原機的 SPFILE 備份過來後改為 INIT File ,修改一下相關的 PATH ,再重新啟動資料庫。開始 Restore Datafile
因為這是一個 Netweaver 的平台,所以 Datafile 的 Layout 和正統 R/3 不同,而我因為是做 SAP 單純還原至 Oracle ,所以有些 Folder Name 被我變更了,所公必須下 set newname 變更。
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
set newname for DATAFILE 1 to '/oradata1/P03/system_1/system.data1' ;
set newname for DATAFILE 2 to '/oradata1/P03/undo_1/undo.data1';
set newname for DATAFILE 3 to '/oradata1/P03/sysaux_1/sysaux.data1';
set newname for DATAFILE 4 to '/oradata1/P03/saux_1/saux.data1';
set newname for DATAFILE 5 to '/oradata1/P03/sr3db_1/sr3db.data1';
set newname for DATAFILE 6 to '/oradata1/P03/sr3db_2/sr3db.data2';
set newname for DATAFILE 7 to '/oradata1/P03/sr3db_3/sr3db.data3';
restore database;
release channel c1;
}
接下來我去 SAP Backup Log 查了需要的 Archive Log Range 為 4199 至 4246,依下列指令還原 Archive Log
run{
allocate channel c1 type 'sbt_tape' parms 'ENV=(NSR_SERVER=XXXbkpnn , NSR_CLIENT=xxxsapp3)';
RESTORE ARCHIVELOG FROM SEQ 4199 UNTIL SEQ 4246;
release channel c1;
}
到此為止,應該可以啟動資料庫了吧,結果上面兩個還原沒一個成功
理論上是 OK 的,但在 Networker 這個產品之下,我們的 Resource 不足,只有兩個 Driver ,同時運行了 D2D2T ,而 Netwoker 在做 Data Staging 時,Source 和 Target 兩份資料都會鎖住不讓你存取,所以我下了兩個 RMAN 的指令,經過漫常的等待,完全沒有回應,直到 Data Staging 做完後,終於開始從磁帶讀到資料了。
但是,有部份資料需要換帶,結果 Driver 在換帶過程又被別人搶去用了,以我所知,NBU 可以在 JOB 上設定 Priority ,TSM 的 Restore JOB Priority 是最高的,所以不太會有這類狀況發生。
我花了一天的時間,倒不回這個 Netweaver 30G 的資料,後來心想,才 30G ,幹麼不直接備份下來到 Networker 後,趁他未做 Data Staging 時趕緊 Restore ,不就直接還原了嗎?
結果我重做了一次備份,不到半小時,就將資料庫 Clone 一份出來了,真不知浪費一天時間在幹麼?
另一個小插曲,熟 Oracle 的人可能會問:「為何不用 alter database begin backup ,然後用 Hot Copy 就好了?」
因為這一個 Database 是 SAP ,當初 SAP 初始安裝會設定一個參數 filesystemio_options ,請看 這邊有解釋,而我並未去調整為asynch ( Oracle Default) 所以在此條件下, Hot Backup 是不允許的,只能經由 RMAN 操作這個資料庫。
最後調整完成後,我也覺得很煩,還是乾脆將原機 OS 備份下來後,還原至另一台,改用 brrestore 來做。
假設相關參數檔都在的狀況下,只需 Restore Control file , Data File 及 Archive Log File ,所以只需下三個指令
brrestore -m 0 <-- 還原 Control File ,他會依照 Init File 內定義的 Control File 位置進行複蓋的動作。
上述指令完成後,啟動資料庫至 Mount ,才能繼續下列動作。
brrestore -m full <-- 還原 Datafile ,此指令會直接還原最後一份備份成功的資料
brrestore -b bcnmhluz.aft -m full <-- 假設你知道要還原的 Backup Log 的 File Name ,可以使用 -b 參數指定, brrestore 會找出這份 Backup Set ,並還原回來。
brrestore -a 4199-4246 還原 archive log 中 sequence 為 4199 ~ 4246 的 Log File
如果相關參數檔都不在的話,就比較麻煩,還是使用原來 RMAN 的方式來做比較方便,由 Oracle 幫你找,不過前題是你倒的出 Control File ,能抓到最後一份 Catalog 。
brrestore 的方法至少要有 SAP 存在於 oracle 目錄下的 sapbackup 及 saparch 這兩個 folder 的相關檔案資訊(summary log 及 backup log) ,還有 Oracle HOME 目錄中 dbs 下的 init[Instance Name].sap 及init[Instance Name].utl 這些檔案才能無誤的運作,當然這些東西是可以用 brrestore 倒出來的,不過等我下次有機會做後再上來補完。這些動作之前也常作,不過不是很清楚了。
SAP help 裏的作法是如此的,有機會再來做一次,因為白天我們的 Networker 都在做 Staging ,又沒機會試了。
我只記得 sapdba 實在是比現在的 brtools 好用多了,不知 SAP 在想什麼。
2012/0622 實際操作了一次 Windows 下的 Brrestore ,狀態跟 UNIX 下的不太一樣,好像在過程中的 Log 是不會作動的。可能要 Restore 完成才會有 Log ,不過也可能跟使用的 Backup API 有關,等 Restore 完成再來確認。
2011年7月19日 星期二
第二十回 Oracle 裏的 TOP N
剛剛又遇到同事詢問這個問題,平常我也不寫程式,都在處理資料庫的問題,一時要寫 SQL 還真寫不出來,找了一些資訊後,趕緊來筆記一下
假設一個Table S,內容如下
LOC INV
----------------- ----------
aaa 20
aaa 30
aaa 50
aaa 60
bbb 60
bbb 60
bbb 70
bbb 90
bbb 100
試著找出每個 LOC 中,INV 最多的前兩筆,用文字編輯器改一改就是要如下結果
LOC INV
---------- ----------
aaa 60
aaa 50
bbb 100
bbb 90
LOC=aaa 中 INV 最大的兩筆為 60 和 50
LOC=bbb 中 INV 最大的兩筆為 100 和 90
所以先 create 一個 Table S
create table s
( loc varchar2(20) not null,
inv number
);
然後將資料 insert
insert into s values('aaa',20);
insert into s values('aaa',30);
......後略
因為 Oracle 沒有 Top N ,所以每次在用這種找出前幾筆的 Function 時,總是很麻煩得用 ROWNUM 來做
如果是一張表格要抓前兩名,其實也不難
select * from (select * from s order by inv desc) where rownum <=2
出來的結果如下
LOC INV
---------- ----------
bbb 100
bbb 90
但是我要的不是這個東西,因此不知在 Oracle 8i 還是 9i 就有了 RANK() 和 DENSE_RANK() 這兩個函數,這邊只依我原有範例說明用法,詳細的說明 這裏 寫的更清楚。
RANK() 會產生一個 column base 在後面的 over 子句下法
所以如果要用 RANK() 產生 TOP N 的結果就如下所示的寫法
select loc,inv,rank() over (order by inv desc ) test from s
LOC INV TEST
---------- ---------- ----------
bbb 100 1
bbb 90 2
bbb 70 3
aaa 60 4
bbb 60 4
bbb 60 4
aaa 50 7
aaa 30 8
aaa 20 9
會發現多了一個 test column 上面記載了排名,特別注意這邊有三筆 60 的記錄,如果使用 row_num 這三筆會被排名為 4,5,6 ,但在 RANK() 的下法中,會統一被規類為排名4
但使用 DENSE_RANK() 時會有什麼結果呢?
select loc,inv,dense_rank() over (order by inv desc ) test from s
LOC INV TEST
---------- ---------- ----------
bbb 100 1
bbb 90 2
bbb 70 3
aaa 60 4
bbb 60 4
bbb 60 4
aaa 50 5
aaa 30 6
aaa 20 7
由此可發現使用 RANK() 時,因為第 5和第6名均被佔據了,所以下一筆會直接代入7,但使用 DENSE_RANK() ,第5名和第6名仍是存在的
但如此還是無法達成原有的需求,不過因為在 over 子句裏還有一個 partition by 的參數,可以做表分割
所以改為下列寫法
select loc,inv from (
select loc, inv,rank() over(partition by loc order by inv desc ) rank from s)
where rank <= 2;
如此就會依據 loc 去分別計算各區的排名,結果就出來了
LOC INV
---------- ----------
aaa 60
aaa 50
bbb 100
bbb 90
但是,原本我以為如果像 SQL Server 有 Top N 可用,配合 Group BY 時是可以有這種功能的,結果我錯了,SQL Server 到了 2005 後也支援 rank() Function ,才可達到類似功能,不然就得寫 SP 才做的到了。
假設一個Table S,內容如下
LOC INV
----------------- ----------
aaa 20
aaa 30
aaa 50
aaa 60
bbb 60
bbb 60
bbb 70
bbb 90
bbb 100
試著找出每個 LOC 中,INV 最多的前兩筆,用文字編輯器改一改就是要如下結果
LOC INV
---------- ----------
aaa 60
aaa 50
bbb 100
bbb 90
LOC=aaa 中 INV 最大的兩筆為 60 和 50
LOC=bbb 中 INV 最大的兩筆為 100 和 90
所以先 create 一個 Table S
create table s
( loc varchar2(20) not null,
inv number
);
然後將資料 insert
insert into s values('aaa',20);
insert into s values('aaa',30);
......後略
因為 Oracle 沒有 Top N ,所以每次在用這種找出前幾筆的 Function 時,總是很麻煩得用 ROWNUM 來做
如果是一張表格要抓前兩名,其實也不難
select * from (select * from s order by inv desc) where rownum <=2
出來的結果如下
LOC INV
---------- ----------
bbb 100
bbb 90
但是我要的不是這個東西,因此不知在 Oracle 8i 還是 9i 就有了 RANK() 和 DENSE_RANK() 這兩個函數,這邊只依我原有範例說明用法,詳細的說明 這裏 寫的更清楚。
RANK() 會產生一個 column base 在後面的 over 子句下法
所以如果要用 RANK() 產生 TOP N 的結果就如下所示的寫法
select loc,inv,rank() over (order by inv desc ) test from s
LOC INV TEST
---------- ---------- ----------
bbb 100 1
bbb 90 2
bbb 70 3
aaa 60 4
bbb 60 4
bbb 60 4
aaa 50 7
aaa 30 8
aaa 20 9
會發現多了一個 test column 上面記載了排名,特別注意這邊有三筆 60 的記錄,如果使用 row_num 這三筆會被排名為 4,5,6 ,但在 RANK() 的下法中,會統一被規類為排名4
但使用 DENSE_RANK() 時會有什麼結果呢?
select loc,inv,dense_rank() over (order by inv desc ) test from s
LOC INV TEST
---------- ---------- ----------
bbb 100 1
bbb 90 2
bbb 70 3
aaa 60 4
bbb 60 4
bbb 60 4
aaa 50 5
aaa 30 6
aaa 20 7
由此可發現使用 RANK() 時,因為第 5和第6名均被佔據了,所以下一筆會直接代入7,但使用 DENSE_RANK() ,第5名和第6名仍是存在的
但如此還是無法達成原有的需求,不過因為在 over 子句裏還有一個 partition by 的參數,可以做表分割
所以改為下列寫法
select loc,inv from (
select loc, inv,rank() over(partition by loc order by inv desc ) rank from s)
where rank <= 2;
如此就會依據 loc 去分別計算各區的排名,結果就出來了
LOC INV
---------- ----------
aaa 60
aaa 50
bbb 100
bbb 90
但是,原本我以為如果像 SQL Server 有 Top N 可用,配合 Group BY 時是可以有這種功能的,結果我錯了,SQL Server 到了 2005 後也支援 rank() Function ,才可達到類似功能,不然就得寫 SP 才做的到了。
2011年7月11日 星期一
第十九回 Oracle 8.1.7 RMAN Backup 時出現錯誤訊息
最近將一台設備使用了類似 Log Shipping 的方式轉移,所以在啟動資料庫時有 Resetlogs
之後幾天使用原來的 Backup Scripts 備份 Archive Log 一直都失敗,會出現以下錯誤
RMAN-03022: compiling command: backup
RMAN-03025: performing implicit partial resync of recovery catalog
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure during compilation of command
RMAN-03013: command type: backup
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20242: specification does not match any archivelog in the recovery catalog
原有的 Rman Archive Log Backup Scripts 如下
run {
allocate channel t1 type disk;
allocate channel t2 type disk;
backup
filesperset 20
format '/disk01/backup/al_%s_%p_%t'
(archivelog until time 'sysdate-7' delete input skip accessible);
release channel t1;
release channel t2;
}
後來查明原因,這是因為我們 Resetlogs 後,系統還沒有產生 7 天後的 Archvelog 可供備份,所以找不到需要備份的檔案。如果你的 Backup Scripts 中,有使用名字來過濾需要備份的檔案時,找不到該檔案也會出現類似的 Error ,其實這應該只是個 Waring 才對。
之後幾天使用原來的 Backup Scripts 備份 Archive Log 一直都失敗,會出現以下錯誤
RMAN-03022: compiling command: backup
RMAN-03025: performing implicit partial resync of recovery catalog
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure during compilation of command
RMAN-03013: command type: backup
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20242: specification does not match any archivelog in the recovery catalog
原有的 Rman Archive Log Backup Scripts 如下
run {
allocate channel t1 type disk;
allocate channel t2 type disk;
backup
filesperset 20
format '/disk01/backup/al_%s_%p_%t'
(archivelog until time 'sysdate-7' delete input skip accessible);
release channel t1;
release channel t2;
}
後來查明原因,這是因為我們 Resetlogs 後,系統還沒有產生 7 天後的 Archvelog 可供備份,所以找不到需要備份的檔案。如果你的 Backup Scripts 中,有使用名字來過濾需要備份的檔案時,找不到該檔案也會出現類似的 Error ,其實這應該只是個 Waring 才對。
2011年3月9日 星期三
小插曲 Data Guard Archive Log Manage (Primary Site)
從 9i 開始到現在 10g (11g 小弟還沒使用過) ,所使用過的 DataGuard 有個缺點,就是設定之後,Archive Log 就必須自己管理,當然也可以不需要理會,完全交給 RMAN 備份去刪除就可以了,只是如果你擔心 Data Guard 的 Standby 在還沒傳輸完成及Apply Archive Log 前,Primary Site 的Log就被備份軟體刪除,你就必須自己控制哪個時間點才能刪除,尤其是有時在 dest_2 設定了 ARCH DELAY=XXX 時,萬一斷線發生時,Archvelog 又被備份軟體刪除就有點麻煩,尤其是對我的終端客戶而言,我可不想建立後一天到晚因為客戶的網路問題往那跑,在 UNIX 上面,可以寫 Shell Script 去控制。這裏僅提供 Primary 端的管理,其實 Standby 端的 Script 更簡單,只要修改幾個位置就可以了。
後來我發現,如果利用 RMAN 備份的話,RMAN 好像會去確認 Dataguard 另一端的 Archive Log 有沒有被 Apply ,進而保留未被 Apply 的 LOG ,一直到該 Archive Log 有被 Apply 後,下次的 RMAN 備份就會將之刪除了,所以這個 Script 其實是不需要了。不過這個特性不知是否是 10G 才有,隱約記得以前好像是沒這麼方便。
其實這個 Scripts 還挺簡陋的,不過我也不知道還有沒有更精簡的方法,至目前為止我都是如此使用的
#!/bin/ksh
export ORACLE_SID=PXX
export SCRIPT_HOME=/oracle/PXX/jobs/sapdr
export LOG_HOME=/oracle/PXX/jobs/logs
export DG_HOST=PXX_DR_HOST
export DG_TNSNAME=PXX_DR
TIME=`date +%m%d%H%M`
remote_cmd=rsh
case $remote_cmd in
rsh)
copy_method=rcp
break
;;
ssh)
copy_method=scp
break
;;
esac
#為了將來如果改使用 SSH 時,不需太多變更,因此加了上面的 Case 判斷
trap "rm /tmp/.lock_DG exit -1" 2 3 5 15
if [ -f /tmp/.lock_DG ] ; then
exit
fi
touch /tmp/.lock_DG
#避免此 Script 被重覆執行,因此用 trap 機制避免
cd $SCRIPT_HOME
#check remote site listener is alive
tnsping $DG_TNSNAME
if [ $? -ne 0 ] ; then
echo DG_HOST not exist > /tmp/rmarch.sh.$TIME
rm /tmp/.lock_log
exit 1
fi
#第一部當然要先確認對方的 TNS Names 是否存在
$remote_cmd $DG_HOST "cd $SCRIPT_HOME;sh ./get_MAX_log_dg.sh"
#從 Standby Site 取得目前己被 Apply 的 MAX Log Sequence#
# get_MAX_log_dg.sh 檔案的內容如下
#--> #!/bin/ksh
#--> export SCRIPT_HOME=/oracle/P02/jobs/sapdr
#--> TIME=`date +%m%d%H%M`
#--> echo "spool dg_log.lst" > $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set echo off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set feedback off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set heading off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "select max(sequence#)" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "from v\$log_history" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "where first_time < sysdate-7/24;" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "spool off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "exit" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> sqlplus '/ as sysdba' @$SCRIPT_HOME/grlist_dg_pri.sql
#--> rm $SCRIPT_HOME/grlist_dg_pri.sql
list1=`$remote_cmd $DG_HOST "cd $SCRIPT_HOME;cat dg_log.lst" | awk ' NR > 1 { print $1 }'`
echo $list1
$remote_cmd $DG_HOST "cd $SCRIPT_HOME;rm dg_log.lst"
echo "set echo off" > $SCRIPT_HOME/grlist_dg.sql
echo "set feedback off" >> $SCRIPT_HOME/grlist_dg.sql
echo "set heading off" >> $SCRIPT_HOME/grlist_dg.sql
echo "spool standby_log.lst" >> $SCRIPT_HOME/grlist_dg.sql
echo "select max(sequence#)" >> $SCRIPT_HOME/grlist_dg.sql
echo "from v\$log_history" >> $SCRIPT_HOME/grlist_dg.sql
#echo "where first_time < sysdate-1;" >> $SCRIPT_HOME/grlist_dg.sql
echo "where first_time < sysdate;" >> $SCRIPT_HOME/grlist_dg.sql
echo "spool off" >> $SCRIPT_HOME/grlist_dg.sql
echo "exit" >> $SCRIPT_HOME/grlist_dg.sql
sqlplus '/ as sysdba' @$SCRIPT_HOME/grlist_dg.sql
list1=`cat standby_log.lst| awk ' NR > 1 { print $1 }'`
echo $list1
echo "set echo off" > getrmlist.sql
echo "set feedback off" >> getrmlist.sql
echo "set heading off" >> getrmlist.sql
echo "set pagesize" >> getrmlist.sql
echo "spool rm_primary_arch.sh" >> getrmlist.sql
echo "select 'rm '||name " >> getrmlist.sql
echo " from v\$archived_log " >> getrmlist.sql
echo " where dest_id=1" >> getrmlist.sql
echo " and sequence#<${list1}" >> getrmlist.sql
echo " and backup_count>0 " >> getrmlist.sql
echo " and archived='YES'" >> getrmlist.sql
echo " and deleted='NO' " >> getrmlist.sql
echo " order by thread#, sequence#;" >> getrmlist.sql
echo "spool off" >> getrmlist.sql
echo "exit" >> getrmlist.sql
#產生要抓取 Archive Log 清單的 SQL ,但是 MAX Log 是由對面抓回來的,由此判斷己被 Standby 端 Apply 才會刪除
sqlplus "/ as sysdba" @getrmlist.sql > /dev/null
#由上面產生的 SQL 再產生要刪除的 Shell Scripts "rm_primary_arch.sh"
rm $SCRIPT_HOME/getrmlist.sql $SCRIPT_HOME/grlist_dg.sql $SCRIPT_HOME/standby_log.lst
#將本 Scripts 執行過程中產生的臨時程式 SQL 及 清單檔清除,Debug 時請將其 Remark 掉
chmod +x rm_primary_arch.sh
. ./rm_primary_arch.sh > /dev/null 2>&1
mv rm_primary_arch.sh $LOG_HOME/rm_primary_arch.sh."$TIME"
rman target / nocatalog msglog=$LOG_HOME/rmlog_ma_history < allocate channel for maintenance type disk;
change archivelog all crosscheck;
delete noprompt expired archivelog all;
release channel;
EOF
#在此是使用 RMAN 的 Maintenance Channel 來做 Crosscheck
find $LOG_HOME/ -name "rm_primary_arch.sh*" -ctime +7 -exec rm {} \;
#每次執行產生的 Log 使用 find 指令來刪除,以免執行的 Log 保留過多,這邊保留七天的 Log File
rm /tmp/.lock_DG
#最後記得 lock file 要刪掉,不然下次就不會再執行了
後來我發現,如果利用 RMAN 備份的話,RMAN 好像會去確認 Dataguard 另一端的 Archive Log 有沒有被 Apply ,進而保留未被 Apply 的 LOG ,一直到該 Archive Log 有被 Apply 後,下次的 RMAN 備份就會將之刪除了,所以這個 Script 其實是不需要了。不過這個特性不知是否是 10G 才有,隱約記得以前好像是沒這麼方便。
其實這個 Scripts 還挺簡陋的,不過我也不知道還有沒有更精簡的方法,至目前為止我都是如此使用的
#!/bin/ksh
export ORACLE_SID=PXX
export SCRIPT_HOME=/oracle/PXX/jobs/sapdr
export LOG_HOME=/oracle/PXX/jobs/logs
export DG_HOST=PXX_DR_HOST
export DG_TNSNAME=PXX_DR
TIME=`date +%m%d%H%M`
remote_cmd=rsh
case $remote_cmd in
rsh)
copy_method=rcp
break
;;
ssh)
copy_method=scp
break
;;
esac
#為了將來如果改使用 SSH 時,不需太多變更,因此加了上面的 Case 判斷
trap "rm /tmp/.lock_DG exit -1" 2 3 5 15
if [ -f /tmp/.lock_DG ] ; then
exit
fi
touch /tmp/.lock_DG
#避免此 Script 被重覆執行,因此用 trap 機制避免
cd $SCRIPT_HOME
#check remote site listener is alive
tnsping $DG_TNSNAME
if [ $? -ne 0 ] ; then
echo DG_HOST not exist > /tmp/rmarch.sh.$TIME
rm /tmp/.lock_log
exit 1
fi
#第一部當然要先確認對方的 TNS Names 是否存在
$remote_cmd $DG_HOST "cd $SCRIPT_HOME;sh ./get_MAX_log_dg.sh"
#從 Standby Site 取得目前己被 Apply 的 MAX Log Sequence#
# get_MAX_log_dg.sh 檔案的內容如下
#--> #!/bin/ksh
#--> export SCRIPT_HOME=/oracle/P02/jobs/sapdr
#--> TIME=`date +%m%d%H%M`
#--> echo "spool dg_log.lst" > $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set echo off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set feedback off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "set heading off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "select max(sequence#)" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "from v\$log_history" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "where first_time < sysdate-7/24;" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "spool off" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> echo "exit" >> $SCRIPT_HOME/grlist_dg_pri.sql
#--> sqlplus '/ as sysdba' @$SCRIPT_HOME/grlist_dg_pri.sql
#--> rm $SCRIPT_HOME/grlist_dg_pri.sql
list1=`$remote_cmd $DG_HOST "cd $SCRIPT_HOME;cat dg_log.lst" | awk ' NR > 1 { print $1 }'`
echo $list1
$remote_cmd $DG_HOST "cd $SCRIPT_HOME;rm dg_log.lst"
echo "set echo off" > $SCRIPT_HOME/grlist_dg.sql
echo "set feedback off" >> $SCRIPT_HOME/grlist_dg.sql
echo "set heading off" >> $SCRIPT_HOME/grlist_dg.sql
echo "spool standby_log.lst" >> $SCRIPT_HOME/grlist_dg.sql
echo "select max(sequence#)" >> $SCRIPT_HOME/grlist_dg.sql
echo "from v\$log_history" >> $SCRIPT_HOME/grlist_dg.sql
#echo "where first_time < sysdate-1;" >> $SCRIPT_HOME/grlist_dg.sql
echo "where first_time < sysdate;" >> $SCRIPT_HOME/grlist_dg.sql
echo "spool off" >> $SCRIPT_HOME/grlist_dg.sql
echo "exit" >> $SCRIPT_HOME/grlist_dg.sql
sqlplus '/ as sysdba' @$SCRIPT_HOME/grlist_dg.sql
list1=`cat standby_log.lst| awk ' NR > 1 { print $1 }'`
echo $list1
echo "set echo off" > getrmlist.sql
echo "set feedback off" >> getrmlist.sql
echo "set heading off" >> getrmlist.sql
echo "set pagesize" >> getrmlist.sql
echo "spool rm_primary_arch.sh" >> getrmlist.sql
echo "select 'rm '||name " >> getrmlist.sql
echo " from v\$archived_log " >> getrmlist.sql
echo " where dest_id=1" >> getrmlist.sql
echo " and sequence#<${list1}" >> getrmlist.sql
echo " and backup_count>0 " >> getrmlist.sql
echo " and archived='YES'" >> getrmlist.sql
echo " and deleted='NO' " >> getrmlist.sql
echo " order by thread#, sequence#;" >> getrmlist.sql
echo "spool off" >> getrmlist.sql
echo "exit" >> getrmlist.sql
#產生要抓取 Archive Log 清單的 SQL ,但是 MAX Log 是由對面抓回來的,由此判斷己被 Standby 端 Apply 才會刪除
sqlplus "/ as sysdba" @getrmlist.sql > /dev/null
#由上面產生的 SQL 再產生要刪除的 Shell Scripts "rm_primary_arch.sh"
rm $SCRIPT_HOME/getrmlist.sql $SCRIPT_HOME/grlist_dg.sql $SCRIPT_HOME/standby_log.lst
#將本 Scripts 執行過程中產生的臨時程式 SQL 及 清單檔清除,Debug 時請將其 Remark 掉
chmod +x rm_primary_arch.sh
. ./rm_primary_arch.sh > /dev/null 2>&1
mv rm_primary_arch.sh $LOG_HOME/rm_primary_arch.sh."$TIME"
rman target / nocatalog msglog=$LOG_HOME/rmlog_ma_history <
change archivelog all crosscheck;
delete noprompt expired archivelog all;
release channel;
EOF
#在此是使用 RMAN 的 Maintenance Channel 來做 Crosscheck
find $LOG_HOME/ -name "rm_primary_arch.sh*" -ctime +7 -exec rm {} \;
#每次執行產生的 Log 使用 find 指令來刪除,以免執行的 Log 保留過多,這邊保留七天的 Log File
rm /tmp/.lock_DG
#最後記得 lock file 要刪掉,不然下次就不會再執行了
訂閱:
文章 (Atom)