XtraBackup實踐(一)備份

qixiaobo發表於2018-01-05

title: XtraBackup實踐(一)備份 tags:

  • xtrabackup
  • mysql
  • 熱備
  • 物理備份 categories: mysql date: 2017-10-28 16:31:16

背景

目前隨著使用者越來越多 db的實時性和穩定性也提出了新的要求

之前的備份邏輯時邏輯備份 隨著磁碟的擴容 也考慮目前再加上物理備份

詳細區別可以從參考下文

邏輯備份

邏輯備份是備份sql語句,在恢復的時候執行備份的sql語句實現資料庫資料的重現。

mysqldump

mysqldump是採用SQL級別的備份機制,他將資料表導成SQL指令碼檔案,是最常用的邏輯備份方法。

物理備份

物理備份就是備份資料檔案了,比較形象點就是cp下資料檔案,但真正備份的時候自然不是的cp這麼簡單。

xtrabackup

是一個用來備份 MySQL資料庫的開源工具。

主要特點:

  1. 線上熱備份。可以備份innodb和myisam。innodb主要應用recovery原理。myisam直接拷貝檔案。

  2. 支援流備份。可以備份到disk,tape和reomot host。–stream=tar ./ | ssh user@remotehost cat “>” /backup/dir/

  3. 支援增量備份。可以利用lsn和基礎備份目錄來進行增量備份。

  4. 支援記錄slave上的master log和master position資訊。

  5. 支援多個程式同時熱備份,xtrabackup的穩定性還是挺好的。

準備

下載XtraBackup

    wget http://www.percona.com/redir/downloads/XtraBackup/LATEST/binary/Linux/x86_64/percona-xtrabackup-2.1.8-733-Linux-x86_64.tar.gz
    
    tar -xvf Percona-XtraBackup-2.4.8-r97330f7-el6-x86_64-bundle.tar
    
    yum install percona-xtrabackup-24-2.4.8-1.el6.x86_64.rpm
複製程式碼

安裝成功後可以執行innobackupex指令

    [root@iZuf65br1kzrdlcne4bxpzZ soft]# innobackupex

    171028 11:05:58 innobackupex: Missing argument
    
    [root@iZuf65br1kzrdlcne4bxpzZ soft]# which innobackupex
    
    /usr/bin/innobackupex
複製程式碼

    #backupWithXtra.sh
    
    #!/bin/sh
    
    #on xtrabackup 2.2.8
    
    # 第一次執行它的時候它會檢查是否有完全備份,否則先建立一個全庫備份
    
    # 當你再次執行它的時候,它會根據指令碼中的設定來基於之前的全備或增量備份進行增量備份
    
    #ocpyang@126.com
    
    
    
    INNOBACKUPEX_PATH=innobackupex  #INNOBACKUPEX的命令
    
    INNOBACKUPEXFULL=/usr/bin//$INNOBACKUPEX_PATH  #INNOBACKUPEX的命令路徑
    
    
    
    #mysql目標伺服器以及使用者名稱和密碼
    
    MYSQL_CMD="--host=192.168.1.7 --user=root --password=root --port=3306"
    
    
    
    MYSQL_UP=" --user=root --password='root' --port=3306 "  #mysqladmin的使用者名稱和密碼
    
    
    
    TMPLOG="/tmp/innobackupex.$$.log"
    
    
    
    MY_CNF=/etc/my.cnf #mysql的配置檔案
    
    
    
    MYSQL=/usr/bin/mysql
    
    
    
    MYSQL_ADMIN=/usr/bin/mysqladmin
    
    
    
    BACKUP_DIR=/home/backup/data # 備份的主目錄
    
    
    
    FULLBACKUP_DIR=$BACKUP_DIR/full # 全庫備份的目錄
    
    
    
    INCRBACKUP_DIR=$BACKUP_DIR/incre # 增量備份的目錄
    
    
    
    FULLBACKUP_INTERVAL=86400 # 全庫備份的間隔週期,時間:秒
    
    
    
    KEEP_FULLBACKUP=1 # 至少保留幾個全庫備份
    
    
    
    logdir=/home/backup/log/
    
    
    
    logfiledate=backup.`date +%Y%m%d%H%M`.txt
    
    
    
    #開始時間
    
    STARTED_TIME=`date +%s`
    
    
    
    
    
    
    
    #############################################################################
    
    
    
    # 顯示錯誤並退出
    
    
    
    #############################################################################
    
    
    
    error()
    
    {
    
        echo "$1" 1>&2
    
        exit 1
    
    }
    
    
    
    
    
    
    
    # 檢查執行環境
    
    
    
    if [ ! -x $INNOBACKUPEXFULL ]; then
    
      error "$INNOBACKUPEXFULL 未安裝或未連結到/usr/bin."
    
    fi
    
    
    
    
    
    
    
    if [ ! -d $BACKUP_DIR ]; then
    
      error "備份目標資料夾:$BACKUP_DIR 不存在."
    
    fi
    
    
    
    
    
    
    
    mysql_status=`netstat -nl | awk 'NR>2{if ($4 ~ /.*:3306/) {print "Yes";exit 0}}'`
    
    
    
    if [ "$mysql_status" != "Yes" ];then
    
        error "MySQL 沒有啟動執行."
    
    fi
    
    
    
    
    
    
    
    
    
    
    
    if ! `echo 'exit' | $MYSQL -s $MYSQL_CMD` ; then
    
     error "提供的資料庫使用者名稱或密碼不正確!"
    
    fi
    
    
    
    
    
    
    
    # 備份的頭部資訊
    
    
    
    echo "----------------------------"
    
    echo
    
    echo "$0: MySQL備份指令碼"
    
    echo "開始於: `date +%F' '%T' '%w`"
    
    echo
    
    
    
    
    
    
    
    #新建全備和差異備份的目錄
    
    
    
    mkdir -p $FULLBACKUP_DIR
    
    mkdir -p $INCRBACKUP_DIR
    
    
    
    
    
    
    
    #查詢最新的完全備份
    
    LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`
    
    
    
    
    
    
    
    # 查詢最近修改的最新備份時間
    
    
    
    LATEST_FULL_BACKUP_CREATED_TIME=`stat -c %Y $FULLBACKUP_DIR/$LATEST_FULL_BACKUP`
    
    
    
    
    
    #如果全備有效進行增量備份否則執行完全備份
    
    if [ "$LATEST_FULL_BACKUP" -a `expr $LATEST_FULL_BACKUP_CREATED_TIME + $FULLBACKUP_INTERVAL + 5` -ge $STARTED_TIME ] ; then
    
        # 如果最新的全備未過期則以最新的全備檔名命名在增量備份目錄下新建目錄
    
        echo -e "完全備份$LATEST_FULL_BACKUP 未過期,將根據$LATEST_FULL_BACKUP 名字作為增量備份基礎目錄名"
    
        echo "                     "
    
        NEW_INCRDIR=$INCRBACKUP_DIR/$LATEST_FULL_BACKUP
    
        mkdir -p $NEW_INCRDIR
    
    
    
        # 查詢最新的增量備份是否存在.指定一個備份的路徑作為增量備份的基礎
    
        LATEST_INCR_BACKUP=`find $NEW_INCRDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n"  | sort -nr | head -1`
    
            if [ ! $LATEST_INCR_BACKUP ] ; then
    
                INCRBASEDIR=$FULLBACKUP_DIR/$LATEST_FULL_BACKUP
    
                echo -e "增量備份將以$INCRBASEDIR 作為備份基礎目錄"
    
                echo "                     "
    
            else
    
                INCRBASEDIR=$INCRBACKUP_DIR/${LATEST_FULL_BACKUP}/${LATEST_INCR_BACKUP}
    
                echo -e "增量備份將以$INCRBASEDIR 作為備份基礎目錄"
    
                echo "                     "
    
            fi
    
    
    
        echo "使用$INCRBASEDIR 作為基礎本次增量備份的基礎目錄."
    
        $INNOBACKUPEXFULL --defaults-file=$MY_CNF --use-memory=4G $MYSQL_CMD --incremental $NEW_INCRDIR --incremental-basedir $INCRBASEDIR > $TMPLOG 2>&1
    
    
    
        #保留一份備份的詳細日誌
    
    
    
        cat $TMPLOG>$logdir/$logfiledate
    
    
    
        if [ -z "`tail -1 $TMPLOG | grep 'innobackupex: completed OK!'`" ] ; then
    
         echo "$INNOBACKUPEX 命令執行失敗:"echo
    
         echo -e "---------- $INNOBACKUPEX_PATH 錯誤 ----------"
    
         cat $TMPLOG
    
         rm -f $TMPLOG
    
         exit 1
    
        fi
    
    
    
        THISBACKUP=`awk -- "/Backup created in directory/ { split( \\\$0, p, \"'\" ) ; print p[2] }" $TMPLOG`
    
        rm -f $TMPLOG
    
    
    
    
    
        echo -n "資料庫成功備份到:$THISBACKUP"
    
        echo
    
    
    
        # 提示應該保留的備份檔案起點
    
    
    
        LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`
    
    
    
        NEW_INCRDIR=$INCRBACKUP_DIR/$LATEST_FULL_BACKUP
    
    
    
        LATEST_INCR_BACKUP=`find $NEW_INCRDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n"  | sort -nr | head -1`
    
    
    
        RES_FULL_BACKUP=${FULLBACKUP_DIR}/${LATEST_FULL_BACKUP}
    
    
    
        RES_INCRE_BACKUP=`dirname ${INCRBACKUP_DIR}/${LATEST_FULL_BACKUP}/${LATEST_INCR_BACKUP}`
    
    
    
        echo
    
        echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #紅色
    
        echo -e "必須保留$KEEP_FULLBACKUP 份全備即全備${RES_FULL_BACKUP}${RES_INCRE_BACKUP}目錄中所有增量備份."
    
        echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #紅色
    
        echo
    
    
    
    
    
    
    
    else
    
        echo  "*********************************"
    
        echo -e "正在執行全新的完全備份...請稍等..."
    
        echo  "*********************************"
    
        $INNOBACKUPEXFULL --defaults-file=$MY_CNF  --use-memory=4G  $MYSQL_CMD $FULLBACKUP_DIR > $TMPLOG 2>&1
    
        #保留一份備份的詳細日誌
    
    
    
        cat $TMPLOG>$logdir/$logfiledate
    
    
    
    
    
        if [ -z "`tail -1 $TMPLOG | grep 'innobackupex: completed OK!'`" ] ; then
    
         echo "$INNOBACKUPEX 命令執行失敗:"echo
    
         echo -e "---------- $INNOBACKUPEX_PATH 錯誤 ----------"
    
         cat $TMPLOG
    
         rm -f $TMPLOG
    
         exit 1
    
        fi
    
    
    
    
    
        THISBACKUP=`awk -- "/Backup created in directory/ { split( \\\$0, p, \"'\" ) ; print p[2] }" $TMPLOG`
    
        rm -f $TMPLOG
    
    
    
        echo -n "資料庫成功備份到:$THISBACKUP"
    
        echo
    
    
    
        # 提示應該保留的備份檔案起點
    
    
    
        LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`
    
    
    
        RES_FULL_BACKUP=${FULLBACKUP_DIR}/${LATEST_FULL_BACKUP}
    
    
    
        echo
    
        echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #紅色
    
        echo -e "無增量備份,必須保留$KEEP_FULLBACKUP 份全備即全備${RES_FULL_BACKUP}."
    
        echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #紅色
    
        echo
    
    
    
    fi
    
    
    
    
    
    
    
    
    
    
    
    
    
    #刪除過期的全備
    
    
    
    echo -e "find expire backup file...........waiting........."
    
    echo -e "尋找過期的全備檔案並刪除">> $logdir/$logfiledate
    
    for efile in $(/usr/bin/find $FULLBACKUP_DIR/ -mtime +6)
    
    do
    
        if [ -d ${efile} ]; then
    
        rm -rf "${efile}"
    
        echo -e "刪除過期全備檔案:${efile}" >> $logdir/$logfiledate
    
        elif [ -f ${efile} ]; then
    
        rm -rf "${efile}"
    
        echo -e "刪除過期全備檔案:${efile}" >> $logdir/$logfiledate
    
        fi;
    
    
    
    done
    
    
    
    if [ $? -eq "0" ];then
    
       echo
    
       echo -e "未找到可以刪除的過期全備檔案"
    
    fi
    
    
    
    
    
    
    
    echo
    
    echo "完成於: `date +%F' '%T' '%w`"
    
    exit 0
複製程式碼

某位好心人放在網路上的備份指令碼【可以自己設定備份間隔,比如一天一全備份 每隔1個小時增量備份】版權和作者資訊均為去除

實際執行結果如下

    ./backupWithXtra.sh: MySQL備份指令碼
    
    開始於: 2017-10-28 14:08:16 6
    
    完全備份2017-10-28_13-54-06 未過期,將根據2017-10-28_13-54-06 名字作為增量備份基礎目錄名
    
    增量備份將以/home/backup/data/full/2017-10-28_13-54-06 作為備份基礎目錄
    
    使用/home/backup/data/full/2017-10-28_13-54-06 作為基礎本次增量備份的基礎目錄.
複製程式碼

執行效果相當不錯

可以考慮crontab了~O(∩_∩)O哈哈~

相關文章