天天看點

xtrabackup自動還原腳本v2

xtrabackup自動還原

************************************************************************************************

應用場景:

************************************************************************************************

1.備份目錄為/backup/full和/backup/incre的架構,前者儲存全備,後者儲存增量備份

2.如全備為/backup/full/2015-04-08_15-14-33則将全備的目錄名2015-04-08_15-14-33

作為/backup/incre/下增量備份的目錄名。這樣設計的初衷在于隻要全備不過期,那麼

這個全備檔案之後的增量備份也不過期.

3.還原時,腳本會自動找到最新的全備和最新全備命名的增量備份目錄,并将增量備份

按照先後順序應用日志到全備中,最後完成還原.

4.該版本增加了是否恢複所有增量備份,預設是全部增量備份.

************************************************************************************************

腳本

************************************************************************************************

#!/bin/sh

#[email protected]

#xtrabackup 2.3.3

# 使用方法:

# ./restore.sh /增量備份父目錄或全備的父目錄名

#eg1:./restore.sh /data/backup/full/

#eg2:./restore.sh /data/backup/incre/

#NOTICE:增量備份還原如果指定檔案,則還原到指定檔案名的上一個檔案末截止.

#即輸入的增量檔案名應為需要截止的增量檔案名的下一個檔案

#NOTE:恢複開始前請確定mysql服務停止以及資料和日志目錄清空,如

# rm -rf /data/mysql/innodb_data/*

# rm -rf /data/mysql/data/*

# rm -rf /data/mysql/mysql_logs/innodb_log/*

echo "*************************************************************************"

echo -e '\e[32m 提示:mysql端口根據實際環境修改. \e[m' #紅色

echo "*************************************************************************"

INNOBACKUPEX=innobackupex

INNOBACKUPEX_PATH=/usr/local/xtrabackup/bin/$INNOBACKUPEX

TMP_LOG="/var/log/restore.$$.log"

MY_CNF=/etc/my.cnf

BACKUP_DIR=/data/backup # 你的備份主目錄

FULLBACKUP_DIR=$BACKUP_DIR/full # 全庫備份的目錄

INCRBACKUP_DIR=$BACKUP_DIR/incre # 增量備份的目錄

MEMORY=2048M # 還原的時候使用的記憶體限制數

ERRORLOG=`grep -i "^log-error" $MY_CNF |cut -d = -f 2`

MYSQLD_SAFE=/data/mysql/bin/mysqld_safe

MYSQL_PORT=33107

#############################################################################

#顯示錯誤

#############################################################################

error()

{

    echo "$1" 1>&2

    exit 1

}

#############################################################################

# 檢查innobackupex錯誤輸出

#############################################################################

check_innobackupex_fail()

{

    if [ -z "`tail -2 $TMP_LOG | grep 'completed OK!'`" ] ; then

    echo "$INNOBACKUPEX指令執行失敗:"; echo

    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不存在.請建立備份主目錄$BACKUP_DIR"

fi

if [ $# != 1 ] ; then

  error "使用方法: $0 使用還原目錄的絕對路徑"

fi

if [ ! -d $1 ]; then

  error "指定的備份目錄:$1不存在."

fi

PORTNUM00=`netstat -lnt|grep ${MYSQL_PORT}|wc -l`

if [ $PORTNUM00 = 1  ];

then

echo -e "\e[31m NOTE:------------------------------------------.\e[m" #紅色

echo -e "\e[31m mysql處于運作狀态,請關閉mysql. \e[m" #紅色

echo -e "\e[31m NOTE:------------------------------------------.\e[m" #紅色

exit 0

fi

################判斷還原增量備份部分還是所有################

echo "*************************************************************************"

echo -e "\e[31m 輸入的增量檔案名應為截止的增量檔案名的下一個檔案.\e[m" #紅色

echo "*************************************************************************"

ipname=''

read -p "輸入截止增量備份名[預設所有]:" ipname

echo

echo "輸入截止增量備份名為:$ipname"

input_value=$1

intpu_res=`echo ${input_value%/*}` 

# Some info output

echo "----------------------------"

echo

echo "$0: MySQL還原腳本"

START_RESTORE_TIME=`date +%F' '%T' '%w`

echo "資料庫還原開始于: $START_RESTORE_TIME"

echo

#PARENT_DIR=`dirname ${intpu_res}`

PARENT_DIR=${intpu_res}

if [ $PARENT_DIR = $FULLBACKUP_DIR ]; then

FULL=`ls -t $FULLBACKUP_DIR |head -1`

FULLBACKUP=${intpu_res}/$FULL

echo "還原完全備份:`basename $FULLBACKUP`"

echo

else

################判斷還原部分增量備份還是所有增量備份################

if [ "$ipname" = '' ];then

 if [ $PARENT_DIR = $INCRBACKUP_DIR ]; then

FULL=`ls -t $FULLBACKUP_DIR |head -1`

FULLBACKUP=$FULLBACKUP_DIR/$FULL

if [ ! -d $FULLBACKUP ]; then

error "全備:$FULLBACKUP不存在."

fi

INCR=`ls -t $INCRBACKUP_DIR/$FULL/ |sort -nr | head -1 ` #查找最後一個增量備份檔案

echo "還原将從全備全備$FULL開始,到增量$INCR結束."

echo

echo "Prepare:完整備份..........."

echo "*****************************"

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

# Prepare增量備份集,即将增量備份應用到全備目錄中,按照增量備份順序即按照時間從舊到最新

for i in `find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n `;

do

#判斷最新全備的lsn

#check_full_file=`find $FULLBACKUP/ -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head  -1`

check_full_lastlsn=$FULLBACKUP/xtrabackup_checkpoints

fetch_full_lastlsn=`grep -i "^last_lsn" ${check_full_lastlsn} |cut -d = -f 2`

######判斷增量備份中第一個增量備份的LSN

#check_incre_file=`find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n |  head -1`

check_incre_lastlsn=$PARENT_DIR/$FULL/$i/xtrabackup_checkpoints

fetch_incre_lastlsn=`grep -i "^last_lsn" ${check_incre_lastlsn} |cut -d = -f 2`

echo "完全備份$FULLBACKUP的LSN值:${fetch_full_lastlsn} "

echo "增量備份$i的LSN值:${fetch_incre_lastlsn} "

if [ "${fetch_incre_lastlsn}" -eq "${fetch_full_lastlsn}" ];then

echo "*****************************************"

echo "LSN相等,不需要prepare!"

echo "*****************************************"

echo

break

else

echo "Prepare:增量備份集$i........"

echo "*****************************"

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$FULL/$i > $TMP_LOG 2>&1

check_innobackupex_fail

if [ $INCR = $i ]; then

break

fi

fi 

######判斷LSN

done

else

error "未知的備份類型"

  fi

else

FULL=`ls -t $FULLBACKUP_DIR |head -1`

FULLBACKUP=$FULLBACKUP_DIR/$FULL

echo "Prepare:完整備份..........."

echo "*****************************"

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

ipt=`stat -c=%Z  $PARENT_DIR/$FULL/$ipname |cut -d = -f 2`

echo "還原的指定增量目錄檔案$ipname的紀元時間為:$ipt"

for i in `find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n `;

do

#判斷for循環取到的檔案名是否為輸入的檔案名,如果是則停止循環

if [ "$i" =  "$ipname" ]; then

break;

else

f01=`stat -c=%Z  $PARENT_DIR/$FULL/$i |cut -d = -f 2`

if [ "$f01" -le "$ipt" ]; then

if [ $PARENT_DIR = $INCRBACKUP_DIR ]; then

if [ ! -d $FULLBACKUP ]; then

error "全備:$FULLBACKUP不存在."

fi

#INCR=`ls -t $INCRBACKUP_DIR/$FULL/ |sort -nr | head -1`

echo "還原将從全備$FULL開始,到增量$ipname結束."

echo

#判斷最新全備的lsn

#check_full_file=`find $FULLBACKUP/ -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head  -1`

check_full_lastlsn=$FULLBACKUP/xtrabackup_checkpoints

fetch_full_lastlsn=`grep -i "^last_lsn" ${check_full_lastlsn} |cut -d = -f 2`

######判斷增量備份中第一個增量備份的LSN

check_incre_file=`find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n |  head -1`

check_incre_lastlsn=$PARENT_DIR/$FULL/$i/xtrabackup_checkpoints

fetch_incre_lastlsn=`grep -i "^last_lsn" ${check_incre_lastlsn} |cut -d = -f 2`

echo "完全備份的LSN:${fetch_full_lastlsn} "

echo "增量備份的LSN:${fetch_incre_lastlsn} "

if [ "${fetch_incre_lastlsn}" -eq "${fetch_full_lastlsn}" ];then

echo "*****************************************"

echo -e "\e[31m LSN不需要prepare或備份間隔期間無資料變化 \e[m" #紅色

echo "*****************************************"

fi 

echo

echo "Prepare:增量備份集$i........"

echo "*****************************"

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$FULL/$i > $TMP_LOG 2>&1

check_innobackupex_fail

######判斷LSN

check_full_lastlsn=$FULLBACKUP/xtrabackup_checkpoints

fetch_full_lastlsn=`grep -i "^last_lsn" ${check_full_lastlsn} |cut -d = -f 2`

echo "完全備份目前的LSN:${fetch_full_lastlsn}"

else

error "未知的備份類型"

fi

else 

echo "查找增量備份檔案完成."

check_full_lastlsn=$FULLBACKUP/xtrabackup_checkpoints    

fetch_full_lastlsn=`grep -i "^last_lsn" ${check_full_lastlsn} |cut -d = -f 2`

echo -e "\e[31m -------------------------------------------- \e[m" #紅色

echo -e "\e[31m 完全備份最終的LSN:${fetch_full_lastlsn} \e[m" #紅色

echo -e "\e[31m -------------------------------------------- \e[m" #紅色

break

fi

fi

done

fi

################判斷還原部分增量備份還是所有增量備份################

fi

echo 

echo "prepare:完整備份以及復原那些未送出的事務..........."

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

echo "*****************************"

echo "資料庫還原中 ...請稍等"

echo "*****************************"

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --copy-back $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

rm -f $TMP_LOG

echo "1.恭喜,還原成功!."

echo "*****************************"

#修改目錄權限

echo "修改mysql目錄的權限."

mysqlcnf="/data/mysql/my.cnf"

mysqldatadir=`grep -i "^basedir" $mysqlcnf |cut -d = -f 2`

`echo 'chown -R mysql:mysql' ${mysqldatadir}`

echo "2.權限修改成功!"

echo "*****************************"

#自動啟動mysql

INIT_NUM=1

if [ ! -x $MYSQLD_SAFE ]; then

  echo "mysql安裝時啟動檔案未安裝到$MYSQLD_SAFE或無執行權限"

  exit 1  #0是執行成功,1是執行不成功

else

echo "啟動本機mysql端口為:$MYSQL_PORT的服務"

$MYSQLD_SAFE --defaults-file=$MY_CNF  > /dev/null &

while  [ $INIT_NUM  -le 10 ]

      do

        PORTNUM=`netstat -lnt|grep ${MYSQL_PORT}|wc -l`

        echo "mysql啟動中....請稍等..."

        sleep 10

        if [ $PORTNUM = 1  ];

        then

echo -e "\e[32m mysql                                      ****啟動成功**** \e[m"

        exit 0

        fi

        INIT_NUM=$(($INIT_NUM +1))

      done

echo -e "\e[31m mysql啟動失敗或啟動時間過長,請檢查錯誤日志 `echo 'cat ' ${ERRORLOG}` \e[m"

echo "*****************************************"

exit 0

fi

END_RESTORE_TIME=`date +%F' '%T' '%w`

echo "資料庫還原完成于: $END_RESTORE_TIME"

exit 0

************************************************************************************************

執行結果:

************************************************************************************************

# ./restore.sh /backup/incre/ 

輸入截止增量備份名[預設所有]:2015-04-10_14-10-49

輸入截止增量備份名為:2015-04-10_14-10-49

----------------------------

./restore.sh: MySQL還原腳本

資料庫還原開始于: 2015-04-10 14:24:51 5

Prepare:完整備份...........

*****************************

還原的指定增量目錄檔案2015-04-10_14-10-49的紀元時間為:1428646269

還原将從全備2015-04-10_14-05-40開始,到增量2015-04-10_14-10-49結束.

完全備份的LSN: 344693290 

增量備份的LSN: 413297865 

Prepare:增量備份集2015-04-10_14-08-19........

*****************************

完全備份目前的LSN: 413297865

還原将從全備2015-04-10_14-05-40開始,到增量2015-04-10_14-10-49結束.

完全備份的LSN: 413297865 

增量備份的LSN: 481905295 

Prepare:增量備份集2015-04-10_14-09-07........

*****************************

完全備份目前的LSN: 481905295

還原将從全備2015-04-10_14-05-40開始,到增量2015-04-10_14-10-49結束.

完全備份的LSN: 481905295 

增量備份的LSN: 550515490 

Prepare:增量備份集2015-04-10_14-10-49........

*****************************

完全備份目前的LSN: 550515490

查找增量備份檔案完成.

 -------------------------------------------- 

 完全備份最終的LSN: 550515490 

 -------------------------------------------- 

prepare:完整備份以及復原那些未送出的事務...........

*****************************

資料庫還原中 ...請稍等

*****************************

1.恭喜,還原成功!.

*****************************

修改mysql目錄的權限.

2.權限修改成功!

*****************************

啟動本機mysql端口為:3306的服務

mysql啟動中....請稍等...

mysql啟動中....請稍等...

mysql啟動中....請稍等...

 mysql                                      ****啟動成功****