資料庫自動備份是資料安全的最後防線。本文提供在 Ubuntu 系統上,使用原生 mysqldump + Shell 腳本 + cron 定時任務的完整落地方案,涵蓋備份腳本編寫、權限控制、定時排程、日誌記錄、舊備份清理與還原驗證的閉環流程。
# 建立備份根目錄(建議掛載獨立磁碟/網路儲存)
mkdir -p /var/backup/mysql
# 設定擁有者與權限(mysql 使用者需可寫入)
chown mysql:mysql /var/backup/mysql
chmod 750 /var/backup/mysql
/usr/local/bin/backup_mysql.sh#!/bin/bash
# MySQL 自動備份腳本
# 功能:全庫備份、壓縮、日誌記錄、保留策略、錯誤通知
set -euo pipefail
# ===== 配置區 =====
DB_USER="root"
DB_PASS="強密碼123!" # 建議改用 .my.cnf 或密鑰庫
DB_HOST="localhost"
DB_PORT="3306"
BACKUP_DIR="/var/backup/mysql"
RETENTION_DAYS=30 # 保留天數
COMPRESS=true # 是否壓縮
LOG_FILE="/var/log/mysql_backup.log"
# ===================
# 確保目錄存在
mkdir -p "$BACKUP_DIR"
# 時間戳
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/mysql_full_${DATE}.sql"
FINAL_FILE="${BACKUP_FILE}"
# 日誌函數
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
log "=== 開始 MySQL 全量備份 ==="
# 執行備份
if mysqldump \
--host="$DB_HOST" \
--port="$DB_PORT" \
--user="$DB_USER" \
--password="$DB_PASS" \
--all-databases \
--single-transaction \
--routines \
--triggers \
--events \
--hex-blob \
--quick \
--lock-tables=false \
> "$BACKUP_FILE" 2>>"$LOG_FILE"; then
log "備份檔案生成成功: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))"
# 壓縮
if [ "$COMPRESS" = true ]; then
if gzip "$BACKUP_FILE"; then
FINAL_FILE="${BACKUP_FILE}.gz"
log "壓縮完成: $FINAL_FILE ($(du -h "$FINAL_FILE" | cut -f1))"
else
log "錯誤: 壓縮失敗,保留未壓縮檔案"
fi
fi
# 清理舊備份
log "清理 ${RETENTION_DAYS} 天前的備份檔案..."
find "$BACKUP_DIR" -type f -name 'mysql_full_*.sql*' -mtime +$RETENTION_DAYS -delete -print | while read f; do
log "刪除過期備份: $f"
done
log "=== 備份任務完成 ==="
else
log "錯誤: mysqldump 執行失敗,請檢查日誌"
exit 1
fi
chmod +x /usr/local/bin/backup_mysql.sh
chown root:root /usr/local/bin/backup_mysql.sh
# 測試執行
/usr/local/bin/backup_mysql.sh
# 檢查結果
ls -lh /var/backup/mysql/
cat /var/log/mysql_backup.log
# 編輯 root 的 crontab
crontab -e
# 每天凌晨 3:01 執行(避開 0 點日誌切割、系統備份等高峰)
1 3 * * * /usr/local/bin/backup_mysql.sh >> /var/log/mysql_backup_cron.log 2>&1
# 進階:每小時增量備份(需啟用 binlog)
# 0 * * * * /usr/local/bin/backup_mysql_incremental.sh
/root/.my.cnf(權限 600)
[mysqldump]
user=root
password=強密碼123!
host=localhost
port=3306
腳本中移除 --password 參數,mysqldump 會自動讀取gpg 或 openssl 加密備份檔案
gpg --symmetric --cipher-algo AES256 "$FINAL_FILE"
rsync、rclone 或 aws s3 cp 同步至遠端儲存# 解壓(如有壓縮)
gunzip -c /var/backup/mysql/mysql_full_20240115_030100.sql.gz > /tmp/restore_test.sql
# 建立測試資料庫
mysql -u root -p -e "CREATE DATABASE restore_test;"
# 還原
mysql -u root -p restore_test < /tmp/restore_test.sql
# 驗證資料完整性
mysql -u root -p -e "SELECT COUNT(*) FROM restore_test.關鍵業務表;"
# 清理測試環境
mysql -u root -p -e "DROP DATABASE restore_test;"
| 維度 | mysqldump (邏輯備份) | Percona XtraBackup (物理備份) |
|---|---|---|
| 備份速度 | 慢(SQL 解析、轉換) | 快(直接複製檔案,近似 IO 速度) |
| 還原速度 | 慢(重建索引、解析 SQL) | 快(複製回資料目錄,啟動即可) |
| 一致性 | --single-transaction (InnoDB) |
熱備份,非阻塞,完整一致性 |
| 跨版本遷移 | 支援良好 | 需相同主版本、相同配置 |
| 適用規模 | < 50GB | > 50GB、TB 級 |
| 複雜度 | 低 | 中(需安裝工具、理解 prepare 階段) |
建立自動備份非終點,而是起點。定期演練還原、驗證資料完整性、測試 RTO/RPO 指標,才能在災難發生時真正挽救業務。將備份狀態納入監控告警(備份失敗、檔案過小、磁碟空間不足),實現備份全生命週期可視化管理。