首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 異地自動備份實戰:Export + FTP/SCP + Cron 零成本容災方案

     編輯:Oracle 資料庫相關知識

前言:大型商業系統的生命線——異地容災

單機房部署在火災、地震、光纖挖斷、存儲陣列雙控故障面前是單點失效。本文基於 Oracle 8i/9i 實戰經驗,構建一套「零授權成本、純腳本驅動、生產驗證」的異地自動備份體系:EXP 全量導出 → 壓縮 → SCP/RSYNC 異地傳輸 → Cron 排程 → 監控告警。

核心命令深度解析

1. EXP (原版導出) —— 雖老但穩,還是有用武之地

三種模式:

  • 使用者模式:exp userid=scott/tiger OWNER=scott FILE=scott.dmp
  • 表模式:exp userid=scott/tiger TABLES=emp,dept FILE=tables.dmp
  • 全庫模式:exp userid='/ as sysdba' FULL=Y FILE=full.dmp (需 EXP_FULL_DATABASE 役)

三種備份類型:

  • 完全 (Complete):INCTYPE=COMPLETE,所有資料。
  • 累積 (Cumulative):INCTYPE=CUMULATIVE,上次完全後所有變更。
  • 增量 (Incremental):INCTYPE=INCREMENTAL,上次任意備份後變更。

本方案採用:全庫模式 + 完全類型,每日一次,簡單可靠。

2. SCP/RSYNC —— 異地傳輸的雙保險

特性SCPRSYNC (推薦)
斷點續傳❌ 不支援✅ --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/

3. Cron —— 守護進程式排程器

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)。

完整腳本實戰代碼

1. full_export.sh —— 全量導出與壓縮

#!/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)。

2. remote_sync.sh —— 異地同步與驗證

#!/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 金鑰 + 命令限制

  1. 備份端生成專用金鑰:ssh-keygen -t ed25519 -f ~/.ssh/dr_backup -N ''。
  2. 公鑰推送至遠端 ~/.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 命令,杜絕互動登入風險。

監控告警閉環

  • 導出/同步失敗:腳本非 0 退出碼觸發 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 升級到 Data Pump (EXPDP) 的演進路徑

維度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 端到端驗證、頻寬限流不影響業務、告警閉環、季度恢復演練。容災備份的本質不是「備份了沒」,而是「能不能在災難發生時、在規定時間內、完整恢復出業務」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved