剛剛又遇到同事詢問這個問題,平常我也不寫程式,都在處理資料庫的問題,一時要寫 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 才做的到了。
2011年7月19日 星期二
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 要刪掉,不然下次就不會再執行了
2011年3月8日 星期二
第十八回 SAP 建立 Oracle Data Guard 出現奇怪的 TNS 問題
上次的發言記錄是去年的 10/25 ,其實因為一些因緣際會,小弟換了家公司繼續 IT 服務,這幾天在建立一套 DataGuard 環境。發生了一些小插曲。
首先建立 DataGuard ,如果你不是用 Broker 來建立的話,依據文字介面的建立方式的部驟其實不難,這個隨便找也有一堆 Step by Step 的部驟,Metalink 上面也有官方參考的文件可看。我建了那麼多套,其實也沒用過 Broker 或是 GUI 建立,總覺得在命令模式下才會清楚自己究竟在幹麼,而且要操作時,只要有 Telnet 就可以完成全部的事情,而透過 Broker 反而也沒比較好操作。
這次建立的環境是 SAP ERP 的環境,依照同樣的部驟,我完成所有設定後,在啟動 log_archive_dest_2 的 MRP Service 後,發現 Archive Log 並沒有造我的期望傳過去,一直出現 Ora 12154 could not resolve service name 的錯誤,可是明明在 SQLPLUS 之下,我己經確認過在兩邊的 Oracle User 的提示字元下都能透過 TNS 順利連線至對方的資料庫,查了半天,確認沒有問題,又試了一次,結果仍然是一樣 ORA 12154 ,這個錯誤訊息就僅僅是 TNSNAMES.ORA 設定錯誤,讓 Oracle 無法解析指定資料庫的位置而己,而我確定我的資訊都是對的。
重新將整個設定全部確認過並重建後,再重新看了一下 Listener.ora 的設定,發現這台機器之前有疑似 DataGuard 的 Listener 存在,從 Alert Log 的保存資料裏面也有對應資訊,可能是從前有測試過該 Function ,所以我就用之前的 Listener 設定重新又做了一次。
終於..........還是不行,只是錯誤訊息不同,更神了,變成 ORA 12541 No Listener,一整個搞不清楚怎麼回事的狀況下,我只覺得我的 Source Instance 是不是瘋了,好像沒有吃到我的設定一樣。將 Metalink 整個翻過了一遍就是沒有對應的錯誤,尤其是 No Listener 才是怪異,根本不可能的事情啊,後來我將環境還原成原來 ORA 12154 的狀態。然後打電話問前同事有沒有遇過這種怪事。
前同事非常熱情的連線過來幫忙看我的狀況,首先,因為我還沒告知他相關的資料庫資訊,因此,他一連上終端機就用 ps -ef 查詢 Oracle Instance 是否有啟動,然後以 su 方式切換至所獲得的 User 資訊的 OS User 下操作,他一試就發現問題,tnsping 並無法 ping 到對方啊,我說怎可能,我測過兩邊的 sqlplus 都連線成功,怎可能 tnsping 不會過。結果他告知我他使用的是 SAP R3 的那個 Service 帳號,不是 Oracle 的帳號。
一聽到這個寶貴的資訊後,我完全了解是怎麼回事了,我馬上切換成 SAP R3 的帳號,echo $TNS_ADMIN ,果然答案出來了,這個 User 有自己的 TNS_ADMIN 位置,所以我從昨天一整個改到翻掉的ORACLE_HOME 裏的那個預設 tnsnames.ora 根本就不是現在啟動的這個資料庫使用的。
但是....................為什麼 Oracle 啟動會使用 SAP 帳號而不是 Oracle 帳號呢? 這是因為,大部份 SAP 都是透過 SAP User 直接執行 SAP 提供的 scripts,就會將 Database 和 R3 Instance 一起啟動,這時,Oracle Process 的 Owner 就會是 SAP 帳號,因為該帳號也有 DBA 權限,所以他是可以操作 Oracle 的檔案的。
但,如果之前啟動是先 su 至 Oracle 帳號啟動資料庫,再 su 成 SAP R3 帳號啟動 R3 ,就不會有這種問題了。而最終的解決方式是,最好將兩個 User 的 TNS_ADMIN 設定的位置都設為相同,這樣才不會有類似的問題發生。在 Oracle ERP 下面也是要注意類似的問題,因為 Oracle ERP 為了相容舊版的Client ,我記得它有多個 ORACLE_HOME ,但在 SAP 上我就沒想到這個問題。
果然是旁觀者清,我查了快一天的問題,沒有 SAP 經驗的同事連線過來2分鐘就搞定了。而原本 ORA 12541 NO Listener 的錯誤是怎麼回事呢,因為之前有人做過設定,在 SAPR3 的 TNSNAMES 裏面是有定義的,但是目地主機早就不存在了,所以我從 Oracle 裏更改對應資料時,他才出現 ORA 12541 ,因為程式讀的根本就不是我後來設定的目地主機。
2010年10月25日 星期一
第十七回 IT 職場生存法則,程序程序再程序
記得2004 還2005年左右,我還在管理某家委外的 SAP 時,因為 Interface (ERP 統稱所有要對外連接的介面叫 Interface) 的部份要透過 Oracle 建立幾個 View ,並且授予權限給能夠存取的子公司存取,還跟網路的防火牆有關,當時我只糊里糊塗的搞清楚哪些 Object 要建立 View,並給哪些人權限,相對應的 SQL 怎麼下,要給哪幾間子公司,就請客戶來開會了,不知各位知不知道當天客戶來了多少人,首先,對口端的連絡人,應該叫他 PM ,但是這種小小的需求我想應該不需要有 PM 吧,然後有一個 SA 跟著來,還有一個客戶那邊的網管,和一個 DBA ,另外來了兩個日本顧問,還有一個翻譯,總共7個人,說實在的我嚇到了,因為我們這邊,只有我一個人負責這些事情。
其實需求都很清楚,客戶那邊有些也有對應的 Specific 了,所以就開始討論細節和 Schedule ,我心裏一直 OS ,SQL 程式碼有了,該給的權限也有了,網路開哪個 Port 連哪個 IP 也知道,這幾件事,我只要二小時就搞定,因為機器統統都是我管的,你們來那麼多人,還要討論什麼 Schedule ,我直接就說,你們回到公司時我就會弄好。直接連過來就是了。
現在我心裏想一想,當時對方那麼多人,個個領的薪水都可能比我當時還高,他們負責的東西還沒我多,憑什麼領那麼多錢? 所以當時兩小時可完成的事情事實上我覺得應該這樣子拆,資料庫的部份因為授權還要請我委外的客戶端開放然後填單,所以工作天三天,網路也是再加三天,然後我處理的時間要二天,頂多文件申請填單可以平行處理,但怕相關人等不在無法授權還要再加個 Buffer ,所以至少要七個工作天。結果我兩個小時就做掉了,我幹麼那麼精實啊我。
雖然這只是一件小小的事情,但看看以日本人為借鏡的客戶端多麼的重視,來了七個人開會,而我們只找了一隻像我一樣的小貓出來叫囂說我二個小時就可以搞定了,搞不好人家還以為我們不專業,不重視他們的需求哩。
所以事情會的多其實也不是什麼重點,當初我直接就開放給客戶使用是因為沒事(雖然我也有經過授權同意,但沒Paper Work),萬一發生了個什麼資料外洩還是規格不對,如果有填單跑程序,出事了,你也還找的到人揹,說是某人同意某人如何如何。不然就是你自己扛了,說實在的也不是官僚,無論在大小公司,有時多嚴謹點也不是什麼壞事啦。只是這其中的拿捏就看個人了,如果當時我喊七天可完成,結果兩天做掉,人家是感謝你,你直接說二小時就可做掉,那不是反而不給人家面子,我們來這麼多人是幹麼吃的不是嗎?
其實需求都很清楚,客戶那邊有些也有對應的 Specific 了,所以就開始討論細節和 Schedule ,我心裏一直 OS ,SQL 程式碼有了,該給的權限也有了,網路開哪個 Port 連哪個 IP 也知道,這幾件事,我只要二小時就搞定,因為機器統統都是我管的,你們來那麼多人,還要討論什麼 Schedule ,我直接就說,你們回到公司時我就會弄好。直接連過來就是了。
現在我心裏想一想,當時對方那麼多人,個個領的薪水都可能比我當時還高,他們負責的東西還沒我多,憑什麼領那麼多錢? 所以當時兩小時可完成的事情事實上我覺得應該這樣子拆,資料庫的部份因為授權還要請我委外的客戶端開放然後填單,所以工作天三天,網路也是再加三天,然後我處理的時間要二天,頂多文件申請填單可以平行處理,但怕相關人等不在無法授權還要再加個 Buffer ,所以至少要七個工作天。結果我兩個小時就做掉了,我幹麼那麼精實啊我。
雖然這只是一件小小的事情,但看看以日本人為借鏡的客戶端多麼的重視,來了七個人開會,而我們只找了一隻像我一樣的小貓出來叫囂說我二個小時就可以搞定了,搞不好人家還以為我們不專業,不重視他們的需求哩。
所以事情會的多其實也不是什麼重點,當初我直接就開放給客戶使用是因為沒事(雖然我也有經過授權同意,但沒Paper Work),萬一發生了個什麼資料外洩還是規格不對,如果有填單跑程序,出事了,你也還找的到人揹,說是某人同意某人如何如何。不然就是你自己扛了,說實在的也不是官僚,無論在大小公司,有時多嚴謹點也不是什麼壞事啦。只是這其中的拿捏就看個人了,如果當時我喊七天可完成,結果兩天做掉,人家是感謝你,你直接說二小時就可做掉,那不是反而不給人家面子,我們來這麼多人是幹麼吃的不是嗎?
2010年8月27日 星期五
第十六回 個人經驗:幾家 Storage 遇過最常見的幾個問題,以EMC 和 IBM 為例
EMC 這家儲存設備廠商所製造的各個型號的 Storage ,在效能和穩定度上的水準一直是不錯的,平台支援度也挺完整的,不過就我常遇到的 CX 等級的機器,其實是有一些問題存在,不過這些問題其實也是個瑕不掩瑜的問題。
首先無論在哪個 Storage 平台都一樣,在安裝之前,請務必參考該 Storage 提供的 Checklist 仔細核對你要使用的平台的作業系統版本及對應的 MultiPath 驅動程式的版本和必須安裝的 Patch 及平台配合需調整的參數,才能在使用時,將問題降到最低。
狀況一:Storage 陷入不明的 Busy 狀態,造成 CPU Load 增加,因為全部都在 I/O Wait 狀態,Application Hang 住,之前就是平台驗證未做好,相對的參數也沒對應好,有過到類似的狀況。後來將 Patch Level 更新後,就沒發生過類似狀況。
另外第二點,既然是 Multipath 的狀態下,請注意你的路徑安裝的方式及 Storage 提供的 MultiPath 使用方式,EMC 的 CLARiiON 及 Symmetrix 的 MultiPath 使用方法是不太一樣的,就如同 IBM 在 DS4 和 DS8 的 MultiPath 亦是不同,所以在 Zoning 和接線方式是要注意的,以免你的 Path 亂掉造成 Storage Controller 誤判而將控制權自行更動。
狀況二:在 IBM DS4 系列曾遇到安裝的工程師在調整 SAN Switch 設定時,接光纖線接錯,造成某張光纖卡故障時,Controller 誤判一直在做切換動作,剛好所屬的 LUN 是在 Cluster 架構下,使得所有同時 Access 到該組 LUN 的 Server 的路徑一起也被切換,使得 I/O 一直不停的 Busy 。因為為了處理這個問題我曾不小心將某全球雙 A 品牌之一的 Mail Server 關閉了半個小時後才回復。
狀況三:在 EMC CX 比較常見,在Disk 被Access 的狀態下,如果突然所有線路直接被拔除,不是瞬斷馬上恢復那種,是真的實體線路連接斷線時,CX 的 Powerpath 下所屬的那個 Path 的 Disk 有非常大的機會會被 Controller Lock 住,此時會有一種狀況,該 Disk 就算線路己經連接回來,你仍然無法使用該 Disk ,有時在 Navigator 下面就可以看到該磁碟的狀況是有些異常的,通常將該 Disk Unassign 再 Assign 後會回復正常,但少數狀況可能需要將目地端主機設備重開,這個問題我在 AIX 上面連接 EMC CX 時經常遇到。
CLARiiON系列的MetaLun在很多場合真的是非常好的一項特性,尤其是原本就有 LVM 架構下的 AIX ,更是強大,幾乎可以不需花費什麼風險就任意的將一個 Disk 放大,不像 DS4 系列號稱可以如此,但是卻是必須要連續空間才有辦法如此使用。
另外 CLARiiON 的前五顆 DISK ,預設是放置 Flare Code OS 用的,這五顆 Disk 內置了整座 CX 的設定及作業系統,系統預設當這五顆 Disk 其中有一顆發生損壞時,是非常危急的一件事,預設第一件事就是要通知所有的人,所以當這五顆 Disk 其中有一顆發生損壞時,就會將 Write Cache 關閉,Write Cache 一關閉,所有接續在本座 CX 儲存設備的系統主機的效能馬上就會陷入無比的低落。
狀況四:EMC CX 系列的前五顆硬碟,只要損壞其中一顆,預設 Controller 的 Write Cache 就會被關閉,此時在使用這個子儲存系統的主機都會發現效能變差,當然在尚未修復前可以透過設定將 Write Cache 再度啟動,讓系統效能恢復,不過 Flare Code OS 所屬的 Disk 故障務必儘速報修將之修復,以免發生遺憾的事情。
狀況五:非常類似 EMC 狀況三的情形,在其他家 Storage 也是會發生的,在 IBM 過去的 ESS 系列,也就是 SHARK 和 DS8000 上面使用 SDD 時會有類似情形,就是當有個 LUN 原本是屬於某個系統存取時,忽然該系統被關閉,緊急改用另一個作業系統接手,而你又未將 LUN 設定在這兩個作業系統都可存取,僅是後來才變更設定,該 LUN 就會被第一個 Access 的作業系統鎖住。在 DS8000 和 ESS 下的 SDD 有個工具叫 lquerypr 可以將這個 Lock 解除。相對的其他廠商也會有類似的工具可以處理類似的問題。
首先無論在哪個 Storage 平台都一樣,在安裝之前,請務必參考該 Storage 提供的 Checklist 仔細核對你要使用的平台的作業系統版本及對應的 MultiPath 驅動程式的版本和必須安裝的 Patch 及平台配合需調整的參數,才能在使用時,將問題降到最低。
狀況一:Storage 陷入不明的 Busy 狀態,造成 CPU Load 增加,因為全部都在 I/O Wait 狀態,Application Hang 住,之前就是平台驗證未做好,相對的參數也沒對應好,有過到類似的狀況。後來將 Patch Level 更新後,就沒發生過類似狀況。
另外第二點,既然是 Multipath 的狀態下,請注意你的路徑安裝的方式及 Storage 提供的 MultiPath 使用方式,EMC 的 CLARiiON 及 Symmetrix 的 MultiPath 使用方法是不太一樣的,就如同 IBM 在 DS4 和 DS8 的 MultiPath 亦是不同,所以在 Zoning 和接線方式是要注意的,以免你的 Path 亂掉造成 Storage Controller 誤判而將控制權自行更動。
狀況二:在 IBM DS4 系列曾遇到安裝的工程師在調整 SAN Switch 設定時,接光纖線接錯,造成某張光纖卡故障時,Controller 誤判一直在做切換動作,剛好所屬的 LUN 是在 Cluster 架構下,使得所有同時 Access 到該組 LUN 的 Server 的路徑一起也被切換,使得 I/O 一直不停的 Busy 。因為為了處理這個問題我曾不小心將某全球雙 A 品牌之一的 Mail Server 關閉了半個小時後才回復。
狀況三:在 EMC CX 比較常見,在Disk 被Access 的狀態下,如果突然所有線路直接被拔除,不是瞬斷馬上恢復那種,是真的實體線路連接斷線時,CX 的 Powerpath 下所屬的那個 Path 的 Disk 有非常大的機會會被 Controller Lock 住,此時會有一種狀況,該 Disk 就算線路己經連接回來,你仍然無法使用該 Disk ,有時在 Navigator 下面就可以看到該磁碟的狀況是有些異常的,通常將該 Disk Unassign 再 Assign 後會回復正常,但少數狀況可能需要將目地端主機設備重開,這個問題我在 AIX 上面連接 EMC CX 時經常遇到。
CLARiiON系列的MetaLun在很多場合真的是非常好的一項特性,尤其是原本就有 LVM 架構下的 AIX ,更是強大,幾乎可以不需花費什麼風險就任意的將一個 Disk 放大,不像 DS4 系列號稱可以如此,但是卻是必須要連續空間才有辦法如此使用。
另外 CLARiiON 的前五顆 DISK ,預設是放置 Flare Code OS 用的,這五顆 Disk 內置了整座 CX 的設定及作業系統,系統預設當這五顆 Disk 其中有一顆發生損壞時,是非常危急的一件事,預設第一件事就是要通知所有的人,所以當這五顆 Disk 其中有一顆發生損壞時,就會將 Write Cache 關閉,Write Cache 一關閉,所有接續在本座 CX 儲存設備的系統主機的效能馬上就會陷入無比的低落。
狀況四:EMC CX 系列的前五顆硬碟,只要損壞其中一顆,預設 Controller 的 Write Cache 就會被關閉,此時在使用這個子儲存系統的主機都會發現效能變差,當然在尚未修復前可以透過設定將 Write Cache 再度啟動,讓系統效能恢復,不過 Flare Code OS 所屬的 Disk 故障務必儘速報修將之修復,以免發生遺憾的事情。
狀況五:非常類似 EMC 狀況三的情形,在其他家 Storage 也是會發生的,在 IBM 過去的 ESS 系列,也就是 SHARK 和 DS8000 上面使用 SDD 時會有類似情形,就是當有個 LUN 原本是屬於某個系統存取時,忽然該系統被關閉,緊急改用另一個作業系統接手,而你又未將 LUN 設定在這兩個作業系統都可存取,僅是後來才變更設定,該 LUN 就會被第一個 Access 的作業系統鎖住。在 DS8000 和 ESS 下的 SDD 有個工具叫 lquerypr 可以將這個 Lock 解除。相對的其他廠商也會有類似的工具可以處理類似的問題。
2010年8月16日 星期一
第十五回 某製造業的 HA 問題
去年底時,有位同事去某製造業 implement HA ,結果一直不順,後來我就過去看,因為狀況真的很怪異。
問題在 HA 設定上都可以順利完成,但在切換演練時會發生兩個問題,一個問題是切換過去後 Application 的 Applet 畫面會出不來,另外一個問題更嚴重,如果我是用 HA 裏的 Move Resource 整個切換過去後,約5~8分鐘的時間,整個系統就會被踢回來。
第一次去看時,我順道帶了一台 Gigabit Ethernet Switch 過去,將網路問題簡單化,只是這兩個問題有時是偶發,有時又不會發生,所以真的很難抓。後來在一次切換成功,等了快半小時以上沒有任何異常的狀態下,我們決定只能先將系統留置在 Standby 端,觀察一個晚上看看。
第二次去看時,發現系統己經自己回到 Master 端在運作,我回去有做了功課,因為做這類 HA 的工作,一開始最好將網路環境的 SPANNING TREE 和 ARP Proxy 關閉,這個原本一開始就跟客戶確認過了,但又再次請教客戶,這些協定有沒有被開啟,但是對口的客戶並不是網管,當天網管也不在公司,無法回答我們。當天又測了好幾次,狀況是一樣的。只好暫時歇兵。
後來不得己請了原廠出馬,看他們在測試的樣子,小弟覺得那個程序確實有值得我學習的地方,但是方法就不說了,老實講,也是亂測一通,把所有可能和不可能的方法都列在白板上,做完失敗就畫掉,交叉分析。其實有些程序在手冊及原理上根本就不存在,這樣也是被列出來測試。最後原廠將整個設定打掉重做,系統忽然就穩定了。因此大家以為從此可以安居樂業了,就快樂的回家。
不過這次穩定的時間確實比較久,大概過了快三天,老現象又發生,後來大家一直在 Review 所有的設定重新檢查,最後客戶發現一件事,為何在 Application 的 Web Server 的設定只有一台主機,此時負責的顧問也注意到了,將兩部主機的設定全加進設定裏後,第一個 Applet 出不來的問題解決了。重覆試了好幾次,都是正常的。但是第二個問題依然是存在,我們又回頭去請教網管,確認是不是不能設的設定有確認過真的沒設。
後來真的確認了,ARP Proxy 被打開了,造成系統切換至 Standby 後我的 ARP Table 不一致,隔沒多久,網路就斷線,然後整個系統就會被踢回 Master 端。
所以在做一些設定時,雖然己經將所需環境及設定告知客戶了,還是得再三確認過才行,這次這個問題,花了快兩週的時間解決。每天許多人都熬到很晚,因為有時又不會發生,根本找不到解釋的原因。所幸 ARP Proxy 關閉了以後,這件事就真的解決了。
問題在 HA 設定上都可以順利完成,但在切換演練時會發生兩個問題,一個問題是切換過去後 Application 的 Applet 畫面會出不來,另外一個問題更嚴重,如果我是用 HA 裏的 Move Resource 整個切換過去後,約5~8分鐘的時間,整個系統就會被踢回來。
第一次去看時,我順道帶了一台 Gigabit Ethernet Switch 過去,將網路問題簡單化,只是這兩個問題有時是偶發,有時又不會發生,所以真的很難抓。後來在一次切換成功,等了快半小時以上沒有任何異常的狀態下,我們決定只能先將系統留置在 Standby 端,觀察一個晚上看看。
第二次去看時,發現系統己經自己回到 Master 端在運作,我回去有做了功課,因為做這類 HA 的工作,一開始最好將網路環境的 SPANNING TREE 和 ARP Proxy 關閉,這個原本一開始就跟客戶確認過了,但又再次請教客戶,這些協定有沒有被開啟,但是對口的客戶並不是網管,當天網管也不在公司,無法回答我們。當天又測了好幾次,狀況是一樣的。只好暫時歇兵。
後來不得己請了原廠出馬,看他們在測試的樣子,小弟覺得那個程序確實有值得我學習的地方,但是方法就不說了,老實講,也是亂測一通,把所有可能和不可能的方法都列在白板上,做完失敗就畫掉,交叉分析。其實有些程序在手冊及原理上根本就不存在,這樣也是被列出來測試。最後原廠將整個設定打掉重做,系統忽然就穩定了。因此大家以為從此可以安居樂業了,就快樂的回家。
不過這次穩定的時間確實比較久,大概過了快三天,老現象又發生,後來大家一直在 Review 所有的設定重新檢查,最後客戶發現一件事,為何在 Application 的 Web Server 的設定只有一台主機,此時負責的顧問也注意到了,將兩部主機的設定全加進設定裏後,第一個 Applet 出不來的問題解決了。重覆試了好幾次,都是正常的。但是第二個問題依然是存在,我們又回頭去請教網管,確認是不是不能設的設定有確認過真的沒設。
後來真的確認了,ARP Proxy 被打開了,造成系統切換至 Standby 後我的 ARP Table 不一致,隔沒多久,網路就斷線,然後整個系統就會被踢回 Master 端。
所以在做一些設定時,雖然己經將所需環境及設定告知客戶了,還是得再三確認過才行,這次這個問題,花了快兩週的時間解決。每天許多人都熬到很晚,因為有時又不會發生,根本找不到解釋的原因。所幸 ARP Proxy 關閉了以後,這件事就真的解決了。
訂閱:
文章 (Atom)