萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 生產級 XtraBackup 物理備份實戰:全備增備腳本、並行壓縮、恢復驗證與坑點避雷

前言

邏輯備份 (mysqldump) 在 500GB 以上數據量面前力不從心:導出慢、導入更慢、佔用大量 CPU。Percona XtraBackup 基於 InnoDB Redo Log 拷貝數據文件,實現熱備份(不鎖表、不阻塞讀寫)、並行壓縮、增量備份、流式傳輸,是生產環境物理備份的事實標準。本文提供生產就緒的自動化腳本、關鍵參數解析、恢復流程與避坑指南。

一、安裝部署

# 1. 下載對應版本包 (Percona 官網)
wget https://www.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.28/binary/tarball/percona-xtrabackup-2.4.28-Linux-x86_64.tar.gz

# 2. 解壓安裝
tar zxf percona-xtrabackup-2.4.28-Linux-x86_64.tar.gz
mkdir -p /usr/local/xtrabackup
cp -r percona-xtrabackup-2.4.28-Linux-x86_64/* /usr/local/xtrabackup/

# 3. 環境變量
echo 'export PATH=$PATH:/usr/local/xtrabackup/bin' >> /etc/profile
source /etc/profile

# 4. 依賴包
yum -y install perl-Time-HiRes perl-DBD-MySQL libev numactl-libs

二、備份賬號最小權限

CREATE USER 'xbkp'@'localhost' IDENTIFIED BY 'Xbkp@StrongPass2024';
GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT, SUPER, CREATE TABLESPACE ON *.* TO 'xbkp'@'localhost';
FLUSH PRIVILEGES;

三、目錄規劃

mkdir -p /data/backup/xtrabackup/{full,incr}
mkdir -p /data/backup/xtrabackup_log

四、生產級自動化備份腳本 /usr/local/sbin/xtrabackup_full_incr.sh

#!/bin/bash
# xtrabackup_full_incr.sh
# 全量備份間隔 23h (82800s),保留 3 份全備及其增量鏈
# 每小時執行一次:0 * * * * /usr/local/sbin/xtrabackup_full_incr.sh >> /data/backup/xtrabackup_log/cron.log 2>&1

set -euo pipefail

INNOBACKUPEX=/usr/local/xtrabackup/bin/innobackupex
MY_CNF=/etc/my.cnf
MYSQL_USER=xbkp
MYSQL_PASS='Xbkp@StrongPass2024'
MYSQL_HOST=localhost
MYSQL_PORT=3306
BACKUP_ROOT=/data/backup/xtrabackup
FULL_DIR=$BACKUP_ROOT/full
INCR_DIR=$BACKUP_ROOT/incr
LOG_DIR=/data/backup/xtrabackup_log
FULL_INTERVAL=82800
KEEP_FULL=3
THREADS=4
COMPRESS_THREADS=2
USE_MEMORY=4G

LOG_FILE=$LOG_DIR/backup_$(date +%Y%m%d_%H%M%S).log
exec >> $LOG_FILE 2>&1

echo "========== $(date '+%F %T') Backup Start =========="

# 1. 檢查環境
[ -x $INNOBACKUPEX ] || { echo "ERROR: innobackupex not found"; exit 1; }
[ -d $BACKUP_ROOT ] || { echo "ERROR: backup root missing"; exit 1; }
mysqladmin -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASS -P$MYSQL_PORT ping >/dev/null 2>&1 || { echo "ERROR: MySQL unreachable"; exit 1; }

mkdir -p $FULL_DIR $INCR_DIR

# 2. 尋找最新有效全備
LATEST_FULL=$(find $FULL_DIR -mindepth 1 -maxdepth 1 -type d -printf '%P\n' | sort -r | head -1)
if [ -n "$LATEST_FULL" ]; then
  LATEST_FULL_TS=$(stat -c %Y "$FULL_DIR/$LATEST_FULL")
  NOW_TS=$(date +%s)
  if [ $((LATEST_FULL_TS + FULL_INTERVAL + 300)) -ge $NOW_TS ]; then
    # 全備未過期 → 增量備份
    echo "Incremental backup based on $LATEST_FULL"
    INCR_BASE=$FULL_DIR/$LATEST_FULL
    # 尋找最新增量
    LATEST_INCR=$(find $INCR_DIR/$LATEST_FULL -mindepth 1 -maxdepth 1 -type d -printf '%P\n' 2>/dev/null | sort -r | head -1)
    [ -n "$LATEST_INCR" ] && INCR_BASE=$INCR_DIR/$LATEST_FULL/$LATEST_INCR

    INCR_TARGET=$INCR_DIR/$LATEST_FULL/incr_$(date +%Y%m%d_%H%M%S)
    mkdir -p $INCR_TARGET

    $INNOBACKUPEX --defaults-file=$MY_CNF --user=$MYSQL_USER --password=$MYSQL_PASS --host=$MYSQL_HOST --port=$MYSQL_PORT \
      --parallel=$THREADS --compress --compress-threads=$COMPRESS_THREADS --use-memory=$USE_MEMORY \
      --incremental $INCR_TARGET --incremental-basedir=$INCR_BASE \
      --no-timestamp 2>&1 | tee -a $LOG_FILE

    if [ ${PIPESTATUS[0]} -eq 0 ]; then
      echo "SUCCESS: Incremental backup to $INCR_TARGET"
    else
      echo "FAILED: Incremental backup"
      exit 1
    fi
  else
    # 全備過期 → 新全備
    goto_full
  fi
else
  # 無全備 → 新全備
  goto_full
fi

# 3. 清理過期備份 (保留 KEEP_FULL 份全備鏈)
echo "Cleaning expired backups..."
find $FULL_DIR -mindepth 1 -maxdepth 1 -type d -mtime +$((KEEP_FULL*1)) -exec rm -rf {} \;
find $INCR_DIR -mindepth 1 -maxdepth 1 -type d -mtime +$((KEEP_FULL*1)) -exec rm -rf {} \;

echo "========== $(date '+%F %T') Backup End =========="
exit 0

: <<'FULL_BACKUP_LABEL'
goto_full:
  echo "Full backup starting..."
  FULL_TARGET=$FULL_DIR/full_$(date +%Y%m%d_%H%M%S)
  mkdir -p $FULL_TARGET
  $INNOBACKUPEX --defaults-file=$MY_CNF --user=$MYSQL_USER --password=$MYSQL_PASS --host=$MYSQL_HOST --port=$MYSQL_PORT \
    --parallel=$THREADS --compress --compress-threads=$COMPRESS_THREADS --use-memory=$USE_MEMORY \
    $FULL_TARGET --no-timestamp 2>&1 | tee -a $LOG_FILE
  if [ ${PIPESTATUS[0]} -eq 0 ]; then
    echo "SUCCESS: Full backup to $FULL_TARGET"
  else
    echo "FAILED: Full backup"
    exit 1
  fi
FULL_BACKUP_LABEL

五、關鍵參數解析

參數含義建議值
--parallel並行拷貝線程數CPU 核心數 50-75%
--compress啟用 qpress 壓縮 (.qp 後綴)生產必開,節省 60-70% 空間
--compress-threads壓縮線程數2-4
--use-memory崩潰恢復階段內存上限物理內存 20-30%
--incremental-basedir增量基準目錄上一輪全備或增備目錄
--no-timestamp不在目標目錄下再創建時間戳子目錄腳本自控目錄結構必加
--slave-info備份從庫時記錄主庫位點從庫備份必加
--safe-slave-backup暫停 SQL 線程確保一致性從庫備份建議加

六、恢復流程(演練必做)

1. 解壓全備

cd /data/backup/xtrabackup/full/full_20240115_020000
for f in *.qp; do qpress -d $f $(dirname $f) && rm -f $f; done

2. 應用 Redo Log (Prepare 階段)

innobackupex --apply-log --use-memory=4G /data/backup/xtrabackup/full/full_20240115_020000
# 若有增量鏈,依序應用
innobackupex --apply-log --redo-only --use-memory=4G /data/backup/xtrabackup/full/full_20240115_020000 \
  --incremental-dir=/data/backup/xtrabackup/incr/full_20240115_020000/incr_20240115_030000
innobackupex --apply-log --redo-only --use-memory=4G /data/backup/xtrabackup/full/full_20240115_020000 \
  --incremental-dir=/data/backup/xtrabackup/incr/full_20240115_020000/incr_20240115_040000
# 最後一輪不加 --redo-only
innobackupex --apply-log --use-memory=4G /data/backup/xtrabackup/full/full_20240115_020000

3. 還原數據文件

systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysql.bak.$(date +%s)
innobackupex --copy-back --use-memory=4G /data/backup/xtrabackup/full/full_20240115_020000
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

4. 驗證數據一致性

mysql -e "CHECKSUM TABLE db1.t1, db2.t2;"
# 對比備份前後 checksum

七、常見坑點與避雷

  1. 版本匹配:XtraBackup 版本必須與 MySQL 大版本對應 (2.4 對應 5.6/5.7,8.0 對應 8.0)
  2. innodb_log_file_size 變更後首次備份會報錯,需先 --apply-log 一次全備
  3. 權限不足:缺 CREATE TABLESPACE 導致 8.0 備份失敗
  4. 磁盤空間:備份目錄預留 1.5x 數據量;壓縮臨時文件佔用額外空間
  5. GTID 一致性:備份從庫加 --slave-info --safe-slave-backup,恢復後 gtid_purged 自動修正
  6. 並行恢復:8.0 支援 --copy-back --parallel 加速還原

八、總結

XtraBackup 以物理拷貝 + Redo Log 重放實現熱備份,配合並行壓縮、增量鏈、自動清理腳本,可支撐 TB 級生產庫 RPO < 1h、RTO < 30min 目標。核心在於:定期演練恢復、監控備份耗時/大小/成功率、版本升級同步升級工具。將備份納入 CI/CD 流水線,才是真正的生產就緒。

copyright © 萬盛學電腦網 all rights reserved