首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

實戰:MySQL 5.6 使用 innobackupex 自動還原腳本完整指南

     編輯:MySQL 綜合教學

前言

在生產環境中,資料庫的備份與還原是 DBA 核心職責之一。Percona XtraBackup 的 innobackupex 工具支援熱備份、增量備份且不阻塞寫入,是 MySQL 物理備份的主流選擇。本文提供一個生產級的自動還原 Shell 腳本,支援全量備份與增量備份的鏈式還原,並包含錯誤檢測、權限修復、服務自動啟動驗證等完整流程。

腳本核心功能

  • 智慧識別備份類型:自動判斷傳入路徑為全量備份或增量備份
  • 增量備份鏈式準備:按時間順序依次 apply-log,確保資料一致性
  • 完整錯誤處理:每步操作皆檢查 completed OK! 關鍵字,失敗即時輸出日誌並保存
  • 自動權限修復:還原後自動讀取 my.cnf 中的 datadir 並執行 chown -R mysql:mysql
  • 服務啟動驗證:啟動 MySQL 後檢查 3306 端口監聽狀態,確認服務可用

使用前提

  1. 已安裝 Percona XtraBackup,innobackupex 位於 /usr/bin/
  2. 備份目錄結構:/backup/full/ 存放全量備份,/backup/incre/ 存放增量備份
  3. MySQL 配置文件:/usr/local/mysql/my.cnf
  4. 執行用戶需具備備份目錄讀取權限及 MySQL 數據目錄寫入權限

腳本完整代碼

#!/bin/sh
# 使用方法:./restore.sh /備份文件的全路徑
# 作者:ocpyang@126.com

INNOBACKUPEX=innobackupex
INNOBACKUPEX_PATH=/usr/bin/$INNOBACKUPEX
TMP_LOG="/var/log/restore.$$.log"
MY_CNF=/usr/local/mysql/my.cnf
BACKUP_DIR=/backup
FULLBACKUP_DIR=$BACKUP_DIR/full
INCRBACKUP_DIR=$BACKUP_DIR/incre
MEMORY=4096M

#############################################################################
# 錯誤處理函數
#############################################################################
error() {
    echo "$1" 1>&2
    exit 1
}

#############################################################################
# 檢查 innobackupex 執行結果
#############################################################################
check_innobackupex_fail() {
    if [ -z "`tail -2 $TMP_LOG | grep 'completed OK!'`" ]; then
        echo "$INNOBACKUPEX 命令執行失敗:"
        echo "---------- $INNOBACKUPEX 錯誤輸出 ----------"
        cat $TMP_LOG
        logfiledate=restore.`date +%Y%m%d%H%M`.txt
        cat $TMP_LOG > /backup/$logfiledate
        rm -f $TMP_LOG
        exit 1
    fi
}

# 參數檢查
if [ ! -x $INNOBACKUPEX_PATH ]; then
    error "$INNOBACKUPEX_PATH 不存在,請確認安裝路徑或軟連結。"
fi

if [ ! -d $BACKUP_DIR ]; then
    error "備份目錄 $BACKUP_DIR 不存在。"
fi

if [ $# != 1 ]; then
    error "用法: $0 還原目錄的絕對路徑"
fi

if [ ! -d $1 ]; then
    error "還原路徑 $1 不存在。"
fi

echo "----------------------------"
echo "$0: MySQL 還原腳本"
START_RESTORE_TIME=`date +'%F %T %w'`
echo "資料庫還原開始於: $START_RESTORE_TIME"
echo

PARENT_DIR=`dirname $1`

# 判斷備份類型:全量備份或增量備份
if [ $PARENT_DIR = $FULLBACKUP_DIR ]; then
    FULLBACKUP=$1
    echo "還原全量備份: `basename $FULLBACKUP`"
    echo
else
    if [ `dirname $PARENT_DIR` = $INCRBACKUP_DIR ]; then
        INCR=`basename $1`
        FULL=`basename $PARENT_DIR`
        FULLBACKUP=$FULLBACKUP_DIR/$FULL

        if [ ! -d $FULLBACKUP ]; then
            error "全量備份 $FULLBACKUP 不存在。"
        fi

        echo "還原全量備份 $FULL 至增量備份 $INCR"
        echo

        # 1. 準備全量備份 (--redo-only)
        echo "Prepare 全量備份集..........."
        echo "*****************************"
        $INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1
        check_innobackupex_fail

        # 2. 依序準備增量備份
        for i in `find $PARENT_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n`; do
            echo "Prepare 增量備份集 $i........"
            echo "*****************************"
            $INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$i > $TMP_LOG 2>&1
            check_innobackupex_fail

            if [ $INCR = $i ]; then
                break
            fi
        done
    else
        error "未知的備份類型"
    fi
fi

# 3. 最後一次 apply-log 回滾未提交事務
echo "準備全量備份集,回滾未提交事務..........."
$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1
check_innobackupex_fail
echo "*****************************"
echo "1. 資料庫還原中 ... 請稍等"
echo "*****************************"

# 4. 複製回原數據目錄
$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --copy-back $FULLBACKUP > $TMP_LOG 2>&1
check_innobackupex_fail

rm -f $TMP_LOG
echo "2. 恭喜,還原成功!"
echo "*****************************"

# 5. 修改目錄權限
echo "修改 MySQL 目錄權限。"
mysqlcnf="/usr/local/mysql/my.cnf"
mysqldatadir=`grep -i "^basedir=" $mysqlcnf`
`echo 'chown -R mysql:mysql' ${mysqldatadir:8}`
echo "3. 權限修改成功!"
echo "*****************************"

# 6. 互動式啟動 MySQL
echo -n "請輸入 1 確認啟動 MySQL: "
read var
echo "您輸入的是 $var"
errorlog=`grep -i "^log-error" $MY_CNF`

if [ $var = 1 ]; then
    echo "MySQL 啟動中............"
    `/usr/local/mysql/bin/mysqld_safe > /dev/null &`
    sleep 10
    PortNum=`netstat -lnt | grep 3306 | wc -l`
    if [ $PortNum = 1 ]; then
        echo "4. MySQL 啟動成功"
        echo "*****************************"
    else
        echo "4. MySQL 啟動失敗,請檢查錯誤日誌 $errorlog"
        echo "*****************************************"
    fi
    exit 0
else
    echo "輸入不正確!"
fi

END_RESTORE_TIME=`date +'%F %T %w'`
echo "資料庫還原完成於: $END_RESTORE_TIME"
exit 0

關鍵步驟解析

增量備份鏈式 Prepare 邏輯

增量備份必須按生成順序依次應用到全量備份上:

  1. 全量備份先執行 --apply-log --redo-only
  2. 每個增量備份依序執行 --apply-log --redo-only --incremental-dir=...
  3. 最後對全量備份執行不帶 --redo-only 的 --apply-log 回滾未提交事務

sort -n 確保按目錄名(通常為時間戳)升序處理,break 在達到目標增量備份時停止。

錯誤日誌保存機制

每次檢查失敗時,會將完整臨時日誌複製到 /backup/restore.YYYYMMDDHHMM.txt,方便事後排查,同時清理臨時文件。

權限修復的實現

從 my.cnf 解析 basedir,去除前綴 basedir= 後執行 chown,避免硬編碼路徑。

生產環境建議優化

  • 去除互動確認:自動化流程中建議移除 read var,改為參數控制或配合編排系統
  • 增加備份校驗:還原前對備份文件完整性進行 checksum 校驗
  • 支援壓縮備份:增加 --decompress 參數支援 xbstream 格式
  • 並行還原:MySQL 5.7+ 可使用 --use-memory 搭配 --parallel 加速
  • 日誌輪轉:/var/log/restore.*.log 建議接入 logrotate 管理

常見問題排查

現象可能原因解決方案
completed OK! 未出現磁盤空間不足、權限問題、備份文件損壞檢查 df -h、確認 mysql 用戶權限、驗證備份完整性
copy-back 後 MySQL 無法啟動datadir 路徑錯誤、selinux、配置文件不匹配核對 my.cnf datadir、臨時關閉 selinux、對比配置參數
增量備份 apply 失敗增量備份序列缺失、LSN 不連續確認增量備份目錄完整、檢查 xtrabackup_checkpoints

總結

本腳本實現了 MySQL 5.6 環境下基於 innobackupex 的全自動還原流程,涵蓋全量與增量備份的完整生命週期。實際部署時建議根據業務 RTO/RPO 要求,結合備份驗證、自動化編排(Ansible/Jenkins)、監控告警構建完整的災備體系。

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