寫一個 MySQL 自動備份與清理腳本 文章首圖

寫一個 MySQL 自動備份與清理腳本

寫一個 MySQL 自動備份與清理腳本

在日常的系統管理工作中,數據就是資產。對於運行 MySQL 資料庫的伺服器而言,定期備份不僅是災難恢復的最後一道防線,更是確保業務連續性的關鍵。雖然許多圖形化工具或雲端服務提供了備份選項,但掌握底層的 Shell 腳本自動化,能讓管理者更靈活地控制備份策略、節省成本並深入理解系統運作。

今天,我們將撰寫一個簡潔且實用的 Shell 腳本,實現兩個核心功能:自動備份指定的 MySQL 資料庫,以及自動清理過期的備份檔案。這個腳本特別針對 Ubuntu 22.04 和 Debian 12 環境優化,並使用系統原生的 mysqldump 工具。

腳本設計邏輯

在編寫腳本之前,我們需要釐清幾個關鍵變數與邏輯:

  1. 認證方式:為了避免在腳本中明文寫入密碼(這是不安全的做法),我們將使用 MySQL 的選項檔案(.my.cnf)來儲存憑證。
  2. 備份策略:使用 mysqldump 將資料庫轉為 SQL 檔案,並透過 gzip 壓縮以節省磁碟空間。
  3. 清理機制:利用 find 命令找出指定天數前的檔案並刪除,這是 Linux 上最標準且高效的做法。

完整腳本範例

請在您的伺服器上建立一個名為 backup_mysql.sh 的檔案,並貼上以下程式碼:

#!/bin/bash

# =================配置區=================
# MySQL 使用者名稱
DB_USER="root"
# 備份目錄路徑
BACKUP_DIR="/var/backups/mysql"
# 保留備份的天數 (例如:7 天)
RETENTION_DAYS=7
# 要備份的資料庫名稱 (若需備份所有資料庫,可留空或改用 --all-databases)
DATABASE_NAME="myapp_db"
# ========================================

# 檢查備份目錄是否存在,若不存在則建立
if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
    echo "建立備份目錄: $BACKUP_DIR"
fi

# 產生備份檔案名稱,包含日期與時間戳記,避免覆蓋
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DATABASE_NAME}_${TIMESTAMP}.sql.gz"

echo "開始備份資料庫: $DATABASE_NAME"

# 執行備份
# --defaults-extra-file 用於指定包含密碼的設定檔,避免命令列顯示密碼
# 注意:請確保 /etc/mysql/backup.cnf 存在且權限設為 600
mysqldump --defaults-extra-file=/etc/mysql/backup.cnf \
          --single-transaction \
          --routines \
          --triggers \
          "$DATABASE_NAME" | gzip > "$BACKUP_FILE"

# 檢查備份是否成功 (exit code 為 0 表示成功)
if [ $? -eq 0 ]; then
    echo "備份成功: $BACKUP_FILE"

    # 清理過期的備份檔案
    echo "開始清理 $RETENTION_DAYS 天前的備份檔案..."
    find "$BACKUP_DIR" -name "${DATABASE_NAME}_*.sql.gz" -type f -mtime +$RETENTION_DAYS -delete
    echo "清理完成"
else
    echo "備份失敗! 請檢查 MySQL 服務狀態或權限設定。"
    exit 1
fi

前置設定與權限配置

為了讓上述腳本安全運行,您必須完成以下兩項設定。

1. 建立 MySQL 認證檔案

請建立一個專門用於備份的 MySQL 使用者(建議僅給予 SELECT, LOCK TABLES 等必要權限),並建立認證檔案 /etc/mysql/backup.cnf

sudo nano /etc/mysql/backup.cnf

在檔案中填入您的 MySQL 帳號密碼:

[client]
user=backup_user
password=your_secure_password
host=localhost

重要提醒:請務必將此檔案的權限設為只有 root 可讀寫,以防止密碼洩露:

sudo chmod 600 /etc/mysql/backup.cnf
sudo chown root:root /etc/mysql/backup.cnf

2. 賦予腳本執行權限並測試

sudo chmod +x /var/backups/mysql/backup_mysql.sh
# 先手動執行一次測試
sudo bash /var/backups/mysql/backup_mysql.sh

自動化排程

腳本測試無誤後,建議使用 cron 設定自動執行。編輯 root 的 crontab:

sudo crontab -e

加入以下行,設定每天凌晨 2:00 執行備份:

0 2 * * * /var/backups/mysql/backup_mysql.sh >> /var/log/mysql_backup.log 2>&1

這樣您就可以在 /var/log/mysql_backup.log 中監控備份紀錄。

常見問題與解決方案

Q1: 執行腳本時出現 "Access denied" 錯誤? 這通常與兩個原因有關:一是 /etc/mysql/backup.cnf 的權限不是 600,MySQL 客戶端會拒絕讀取非嚴格控制的檔案;二是 MySQL 使用者本身沒有足夠的權限。請先檢查檔案權限,並確認該使用者在 MySQL 中擁有對應資料庫的 SELECTLOCK TABLES 權限。

Q2: 備份檔案太大或空間不足? 目前的腳本已使用 gzip 壓縮,通常能減少 50%-80% 的空間。若空間依然吃緊,可以考慮以下優化:

  • 增加 RETENTION_DAYS 的值,延長保留時間。
  • 將備份檔案轉移至遠端儲存(如 AWS S3 或 Google Cloud Storage),可使用 aws s3 cpgsutil 指令在腳本末尾追加上傳動作。
  • 若資料庫極大,可考慮使用 xtrabackup 進行物理備份,而非邏輯備份的 mysqldump

小結

透過這個簡單的 Shell 腳本,我們不僅實現了資料庫的自動化備份,更建立了自動清理機制,避免了伺服器磁碟空間被舊備份填滿的風險。在 Linux 系統管理中,自動化是減輕日常負擔、提升系統穩定性的最佳途徑。建議您根據實際環境調整備份頻率與保留策略,並定期驗證備份檔案的完整性,確保在緊急時刻能順利還原資料。