專案背景與需求
- 平台:IBM P570 / AIX 5.3 / Oracle 9.2.0.6
- 業務表
T_SMS:每日 700 萬筆簡訊歷史,按月日分區 (如 P01_01 表 1 月 1 日)。
- 痛點:單表龐大導致索引失效、查詢效能差。
- 策略:保留近 3 天資料於生產庫,歷史資料每日匯出遷移至歸檔庫,查詢導向歸檔庫分流壓力。
自動化排程架構
| 時間 | 動作 | 工具 |
| 00:30 | Exp 匯出前一天分區 → DMP | Shell 腳本 + Crontab |
| 03:30 | FTP 傳輸 DMP 至歸檔庫 | FTP 自動腳本 |
| 04:30 | Imp 匯入歸檔庫 | Imp 腳本 + Crontab (歸檔端) |
核心 Exp 腳本 (/sms/exp.sh) 深度解析
1. 日期運算函數:取得 N 天前的 MMDD 格式
GetPrevDate() {
str=$1 # YYYYMMDD
days=$2 # 往前天數
yy=$(echo $str | cut -c1-4)
mm=$(echo $str | cut -c5-6)
dd=$(echo $str | cut -c7-8)
sav_dd=$days
days=$(expr $days - $dd)
while [ $days -ge 0 ]; do
mm=$(expr $mm - 1)
[ $mm -eq 0 ] && mm=12 && yy=$(expr $yy - 1)
aaa=$(cal $mm $yy)
bbb=$(echo $aaa | awk '{print $NF}')
days=$(expr $days - $bbb)
done
dd=$(expr 0 - $days)
[ ${#dd} -eq 1 ] && dd=0$dd
[ ${#mm} -eq 1 ] && mm=0$mm
echo ${mm}_${dd}
}
2. 變數設定與 Exp 執行
todayDate=$(date "+%Y%m%d")
thisday=$(GetPrevDate ${todayDate} 2) # 取前天,如 08_08
dmpfile="/sms/t_sms.dmp"
logfile="/sms/t_sms_${thisday}.log"
partition="t_sms:P${thisday}"
exp sms/sms \
rows=y indexes=n compress=n \
buffer=204800000 direct=y feedback=100000 \
file=$dmpfile log=$logfile tables=$partition
關鍵參數說明
tables=t_sms:P08_08:指定分區級匯出,核心需求。
direct=y:直接路徑匯出,繞過 SQL 層,效能大幅提升。
buffer=200MB:大緩衝減少 I/O 往返。
feedback=100000:每 10 萬行顯示進度點。
indexes=n:不匯出索引,歸檔庫重建更彈性。
部署步驟
- Oracle 用戶登入小型機。
- 腳本置於
/sms/exp.sh,chmod 755。
crontab -e 加入:30 0 * * * /sms/exp.sh。
- 建立 FTP 帳號,歸檔端配置對應下載/匯入排程。
避坑與優化建議
- 時區一致性: 生產/歸檔庫時區必須同步,避免分區名稱計算偏差。
- 磁碟空間監控: 匯出前檢查目標檔案系統可用空間 > 預估 DMP 大小 1.5 倍。
- 並行匯出 (10g+): 升級後可使用
expdp PARALLEL=4 進一步縮短窗口。
- 分區維護: 定期
ALTER TABLE ... DROP PARTITION 清理生產庫舊分區,釋放空間。
- 錯誤通知: 腳本加入退出碼檢查,失敗時郵件/簡訊告警 DBA。