mkdir -p /backup/mysqlbackup
/backup/mysqlbackup/mysql_autobackup.sh#!/bin/bash
# 每日全量備份腳本
FILENAME=$(date +%Y%m%d)
DB_NAME="your_database"
DB_USER="root"
DB_PASS="your_password" # 建議用 .my.cnf 或密鑰文件避免明文
BAK_DIR="/backup/mysqlbackup"
/usr/bin/mysqldump --opt --single-transaction --master-data=2 \
-u${DB_USER} -p${DB_PASS} ${DB_NAME} | gzip > ${BAK_DIR}/${DB_NAME}_${FILENAME}.sql.gz
# 保留 30 天
find ${BAK_DIR} -name "${DB_NAME}_*.sql.gz" -mtime +30 -delete
chmod +x /backup/mysqlbackup/mysql_autobackup.sh crontab -e # 每天 01:01 執行 01 01 * * * /bin/bash /backup/mysqlbackup/mysql_autobackup.sh
log_bin(Binlog)ROW(增量解析準確)expire_logs_days 設定保留天數(如 7)/backup/mysql/ ├── full/ # 全量備份 ├── incremental/ # 增量備份 └── logs/ # 備份日誌
full_backup.sh#!/bin/bash
# 全量備份 + 刷新 Binlog
DATE=$(date +%Y%m%d)
BAK_DIR="/backup/mysql/full"
LOG_FILE="/backup/mysql/logs/full_${DATE}.log"
echo "=== $(date) Full Backup Start ===" >> ${LOG_FILE}
/usr/bin/mysqldump --flush-logs --single-transaction --master-data=2 \
-u${DB_USER} -p${DB_PASS} ${DB_NAME} | gzip > ${BAK_DIR}/${DB_NAME}_${DATE}.sql.gz
echo "=== $(date) Full Backup Done ===" >> ${LOG_FILE}
# 清理 35 天前全量備份
find ${BAK_DIR} -name "${DB_NAME}_*.sql.gz" -mtime +35 -delete
incremental_backup.sh#!/bin/bash
# 增量備份:基於 Binlog
DATE=$(date +%Y%m%d)
BAK_DIR="/backup/mysql/incremental"
BINLOG_DIR="/var/lib/mysql" # 根據實際調整
BINLOG_INDEX="${BINLOG_DIR}/mysql-bin.index"
LOG_FILE="/backup/mysql/logs/inc_${DATE}.log"
echo "=== $(date) Incremental Backup Start ===" >> ${LOG_FILE}
# 1. 刷新 Binlog 生成新文件
/usr/bin/mysqladmin -u${DB_USER} -p${DB_PASS} flush-logs
# 2. 解析昨天產生的 Binlog
START_TIME=$(date -d "1 day ago" +"%Y-%m-%d %H:%M:%S")
for BINLOG_FILE in $(cat ${BINLOG_INDEX} | awk -F'/' '{print $NF}'); do
/usr/bin/mysqlbinlog --start-datetime="${START_TIME}" \
-d ${DB_NAME} ${BINLOG_DIR}/${BINLOG_FILE} | gzip >> ${BAK_DIR}/inc_${DATE}.sql.gz
done
echo "=== $(date) Incremental Backup Done ===" >> ${LOG_FILE}
# 清理 32 天前增量備份
find ${BAK_DIR} -name "inc_*.sql.gz" -mtime +32 -delete
# 全量:每天 03:01 01 03 * * * /bin/bash /backup/mysql/full_backup.sh # 增量:每小時執行(或每天 04:00) 00 04 * * * /bin/bash /backup/mysql/incremental_backup.sh
# 在備份腳本末尾添加
RSYNC_PASS="/etc/rsync.passwd"
REMOTE_USER="backup"
REMOTE_HOST="10.0.0.100"
REMOTE_DIR="/remote/backup/mysql"
/usr/bin/rsync -avz --delete --password-file=${RSYNC_PASS} \
/backup/mysql/ ${REMOTE_USER}@${REMOTE_HOST}::${REMOTE_DIR}
gunzip < backup.sql.gz | mysql -u root -p db_namemysqlbinlog inc_20230101.sql.gz | mysql -u root -p db_namemysqlbinlog --stop-datetime="2023-01-01 12:00:00" ...建議:每月至少一次完整恢復演練,記錄 RTO/RPO 實測值。
| 問題 | 解決 |
|---|---|
| mysqldump 鎖表影響業務 | InnoDB 必加 --single-transaction;MyISAM 無解,建議從庫備份 |
| 備份文件過大傳輸慢 | 分庫分表備份、並行壓縮 pigz、增量備份為主 |
| Binlog 衝突導致增量解析失敗 | 確保 binlog_format=ROW,避免 DDL 衝突 |
| 密碼明文在腳本/進程列表 | 使用 [client] 寫入 ~/.my.cnf (chmod 600),腳本不帶 -p |
| 磁盤空間耗盡 | 配置 df -h 監控告警,備份腳本加空間檢查 |
| 從庫備份延遲導致數據不一致 | 備份前 STOP SLAVE,備份後 START SLAVE,或用 LVM 快照/Percona XtraBackup |
**備份不僅是備份,更是可恢復的演練。** 從基礎的每日全量 gzip,到全量+增量+異地同步+定期演練,構建分層備份體系。核心原則:單事務一致性、Binlog 為增量基石、密碼不落盤、恢復定期驗證、工具升級為 XtraBackup。讓備份成為業務連續性的基石,而非僅僅是一個定時任務。