單機房部署在火災、地震、光纖挖斷、存儲陣列雙控故障面前是單點失效。本文基於 Oracle 8i/9i 實戰經驗,構建一套「零授權成本、純腳本驅動、生產驗證」的異地自動備份體系:EXP 全量導出 → 壓縮 → SCP/RSYNC 異地傳輸 → Cron 排程 → 監控告警。
三種模式:
exp userid=scott/tiger OWNER=scott FILE=scott.dmpexp userid=scott/tiger TABLES=emp,dept FILE=tables.dmpexp userid='/ as sysdba' FULL=Y FILE=full.dmp (需 EXP_FULL_DATABASE 役)三種備份類型:
INCTYPE=COMPLETE,所有資料。INCTYPE=CUMULATIVE,上次完全後所有變更。INCTYPE=INCREMENTAL,上次任意備份後變更。本方案採用:全庫模式 + 完全類型,每日一次,簡單可靠。
| 特性 | SCP | RSYNC (推薦) |
|---|---|---|
| 斷點續傳 | ❌ 不支援 | ✅ --partial --append-verify |
| 增量傳輸 | ❌ 全量覆寫 | ✅ 僅傳輸差異塊 |
| 壓縮傳輸 | ❌ 無 | ✅ -z 啟用 zlib |
| 驗證完整性 | 需額外 md5sum | ✅ -c checksum 驗證 |
| 頻寬限制 | ❌ | ✅ --bwlimit=KBps |
生產命令:
rsync -avzc --partial --append-verify --bwlimit=50000 \
/backup/exp_$(date +%m%d).dmp.gz \
oraback@dr-server:/backup/remote/
crontab -e 編輯 oracle 使用者排程:
# 分 時 日 月 週 命令
10 23 * * * /home/oracle/scripts/full_export.sh >> /home/oracle/logs/export_$(date +\%Y\%m\%d).log 2>&1
30 23 * * * /home/oracle/scripts/remote_sync.sh >> /home/oracle/logs/sync_$(date +\%Y\%m\%d).log 2>&1
關鍵細節:
logrotate 保留 30 天。source ~/.bash_profile 載入環境變數 (ORACLE_HOME, ORACLE_SID, PATH, NLS_LANG)。#!/bin/bash
# 環境變數
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1
export ORACLE_SID=PROD
export PATH=$ORACLE_HOME/bin:$PATH
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
export BACKUP_DIR=/backup/export
export LOG_DIR=/home/oracle/logs
export DATE_TAG=$(date +%m%d)
export DMP_FILE=${BACKUP_DIR}/exp_${DATE_TAG}.dmp
export LOG_FILE=${LOG_DIR}/exp_${DATE_TAG}.log
export GZ_FILE=${DMP_FILE}.gz
# 清理 7 天前舊備份
find ${BACKUP_DIR} -name "exp_*.dmp.gz" -mtime +7 -delete
find ${LOG_DIR} -name "exp_*.log" -mtime +7 -delete
# 執行導出
echo "=== $(date) START EXPORT ===" | tee -a ${LOG_FILE}
exp '/ as sysdba' FULL=Y FILE=${DMP_FILE} LOG=${LOG_FILE} COMPRESS=Y CONSISTENT=Y BUFFER=10485760
EXP_STATUS=$?
echo "=== $(date) EXPORT END, STATUS=${EXP_STATUS} ===" | tee -a ${LOG_FILE}
# 壓縮 (釋放磁碟空間、加速傳輸)
if [ ${EXP_STATUS} -eq 0 ]; then
gzip -f ${DMP_FILE}
echo "=== $(date) COMPRESS DONE: ${GZ_FILE} ===" | tee -a ${LOG_FILE}
else
echo "!!! EXPORT FAILED, SKIP COMPRESS !!!" | tee -a ${LOG_FILE}
exit 1
fi
參數解析:CONSISTENT=Y 確保導出資料一致性 (內部設定 SET TRANSACTION READ ONLY);BUFFER=10M 增大內部緩衝減少 I/O;COMPRESS=Y 導出時合併 Extents (匯入時建立單一 Extent)。
#!/bin/bash
source /home/oracle/.bash_profile
export BACKUP_DIR=/backup/export
export REMOTE_USER=oraback
export REMOTE_HOST=dr-server
export REMOTE_DIR=/backup/remote
export DATE_TAG=$(date +%m%d)
export GZ_FILE=${BACKUP_DIR}/exp_${DATE_TAG}.dmp.gz
export LOG_FILE=/home/oracle/logs/sync_$(date +%Y%m%d).log
echo "=== $(date) START RSYNC ===" | tee -a ${LOG_FILE}
# 傳輸前本地 MD5
LOCAL_MD5=$(md5sum ${GZ_FILE} | awk '{print $1}')
echo "Local MD5: ${LOCAL_MD5}" | tee -a ${LOG_FILE}
# rsync 傳輸
rsync -avzc --partial --append-verify --bwlimit=50000 \
${GZ_FILE} \
${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/ \
>> ${LOG_FILE} 2>&1
RSYNC_STATUS=$?
# 傳輸後遠端 MD5 驗證
if [ ${RSYNC_STATUS} -eq 0 ]; then
REMOTE_MD5=$(ssh ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${REMOTE_DIR}/$(basename ${GZ_FILE})" | awk '{print $1}')
echo "Remote MD5: ${REMOTE_MD5}" | tee -a ${LOG_FILE}
if [ "${LOCAL_MD5}" = "${REMOTE_MD5}" ]; then
echo "=== $(date) MD5 MATCH, SYNC SUCCESS ===" | tee -a ${LOG_FILE}
else
echo "!!! $(date) MD5 MISMATCH, DATA CORRUPTION !!!" | tee -a ${LOG_FILE}
# 觸發告警 (郵件/短信/企業微信)
/home/oracle/scripts/alert.sh "DR Sync MD5 Mismatch: ${GZ_FILE}"
exit 1
fi
else
echo "!!! $(date) RSYNC FAILED, STATUS=${RSYNC_STATUS} !!!" | tee -a ${LOG_FILE}
/home/oracle/scripts/alert.sh "DR Sync Failed: ${GZ_FILE}"
exit 1
fi
ssh-keygen -t ed25519 -f ~/.ssh/dr_backup -N ''。~/.ssh/authorized_keys,前綴限制:command="/home/oraback/validate_rsync.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3... oracle@prod-server
validate_rsync.sh 僅允許 rsync --server 命令,杜絕互動登入風險。
alert.sh (郵件/短信/Webhook)。if [ $(stat -c%s ${GZ_FILE}) -lt 100000000 ]; then alert; fi (小於 100MB 異常)。df -h ${REMOTE_DIR} 監控使用率 > 85% 告警。find ${REMOTE_DIR} -name 'exp_*.dmp.gz' -mtime -1 必須存在,否則告警「備份中斷超過 24h」。| 維度 | EXP (原版) | EXPDP (Data Pump) |
|---|---|---|
| 效能 | 單執行緒、Server Process 搬運資料 | 並行 Worker、直接路徑、非同步 I/O |
| 並行度 | 無 | PARALLEL=8 |
| 壓縮 | 僅 COMPRESS=Y (合併 Extents) | COMPRESSION=ALL/METADATA_ONLY/DATA_ONLY (真實壓縮) |
| 加密 | 無 | ENCRYPTION=ALL (密碼/錢包/雙重) |
| 網路模式 | 無 (需本地檔案再傳) | NETWORK_LINK 直接跨庫匯入 |
| 可重啟 | 無 | Master Table 記錄狀態,RESTARTABLE |
| 版本相容 | 僅同版本/向上相容 | VERSION=11.2 跨版本匯出 |
建議:Oracle 10g+ 新專案直接上 Data Pump;存量 8i/9i 系統可沿用 EXP+RSYNC,平滑遷移時同步切換。
這套方案在某省稅務系統 (Oracle 9i, 2TB, Solaris 10) 穩定運行 5 年 +,RPO = 24h (每日全量),RTO = 4h (解壓+匯入)。核心成功要素:腳本冪等性、MD5 端到端驗證、頻寬限流不影響業務、告警閉環、季度恢復演練。容災備份的本質不是「備份了沒」,而是「能不能在災難發生時、在規定時間內、完整恢復出業務」。