xtrabackup自動還原v2
************************************************************************************************
應用場景:
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
#
# 使用方法:
# ./restore.sh /增量備份父目錄
#NOTE:恢複開始前請確定mysql服務停止以及資料和日志目錄清空,如
# rm -rf /usr/local/mysql/innodb_data/*
# rm -rf /usr/local/mysql/data/*
# rm -rf /usr/local/mysql/mysql_logs/innodb_log/*
INNOBACKUPEX=innobackupex
INNOBACKUPEX_PATH=/usr/local/xtrabackup/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 # 還原的時候使用的記憶體限制數
ERRORLOG=`grep -i "^log-error" $MY_CNF |cut -d = -f 2`
MYSQLD_SAFE=/usr/local/mysql/bin/mysqld_safe
MYSQL_PORT=3306
#############################################################################
#顯示錯誤
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
fi
# 選項檢測
if [ ! -x $INNOBACKUPEX_PATH ]; then
error "$INNOBACKUPEX_PATH在指定路徑不存在,請确認是否安裝或核實連結是否正确."
fi
if [ ! -d $BACKUP_DIR ]; then
error "備份目錄$BACKUP_DIR不存在.請建立備份主目錄$BACKUP_DIR"
if [ $# != 1 ] ; then
error "使用方法: $0 使用還原目錄的絕對路徑"
if [ ! -d $1 ]; then
error "指定的備份目錄:$1不存在."
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" #紅色
exit 0
fi
################判斷還原增量備份部分還是所有################
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"
#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
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
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
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結束."
#判斷最新全備的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 "LSN不需要prepare!"
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
fi
######判斷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}"
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" #紅色
break
fi
done
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 "資料庫還原中 ...請稍等"
$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --copy-back $FULLBACKUP > $TMP_LOG 2>&1
rm -f $TMP_LOG
echo "1.恭喜,還原成功!."
#修改目錄權限
echo "修改mysql目錄的權限."
mysqlcnf="/usr/local/mysql/my.cnf"
mysqldatadir=`grep -i "^basedir" $mysqlcnf |cut -d = -f 2`
`echo 'chown -R mysql:mysql' ${mysqldatadir}`
echo "2.權限修改成功!"
#自動啟動mysql
INIT_NUM=1
if [ ! -x $MYSQLD_SAFE ]; then
echo "mysql安裝時啟動檔案未安裝到$MYSQLD_SAFE或無執行權限"
exit 1 #0是執行成功,1是執行不成功
echo "啟動本機mysql端口為:$MYSQL_PORT的服務"
$MYSQLD_SAFE --defaults-file=$MY_CNF > /dev/null &
while [ $INIT_NUM -le 8 ]
do
PORTNUM=`netstat -lnt|grep ${MYSQL_PORT}|wc -l`
echo "mysql啟動中....請稍等..."
sleep 5
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
END_RESTORE_TIME=`date +%F' '%T' '%w`
echo "資料庫還原完成于: $END_RESTORE_TIME"
執行結果:
# ./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
完全備份的LSN: 413297865
增量備份的LSN: 481905295
Prepare:增量備份集2015-04-10_14-09-07........
完全備份目前的LSN: 481905295
完全備份的LSN: 481905295
增量備份的LSN: 550515490
Prepare:增量備份集2015-04-10_14-10-49........
完全備份目前的LSN: 550515490
查找增量備份檔案完成.
--------------------------------------------
完全備份最終的LSN: 550515490
prepare:完整備份以及復原那些未送出的事務...........
資料庫還原中 ...請稍等
1.恭喜,還原成功!.
修改mysql目錄的權限.
2.權限修改成功!
啟動本機mysql端口為:3306的服務
mysql啟動中....請稍等...