MySQL數據庫的二進制日誌binlog記錄了對數據庫的全量DDL和DML操做,對數據庫的point to point災難恢復起着沒法替代的關鍵做用。所以,基於此類考慮,須要對生產環境產生的binlog作好相應的備份措施。
mysql
這裏主要談及2種備份方法,一種經過腳本定時調度的方式,強行切換binlog,增量備份二進制binlog。另外一種則是經過mysqlbinlog的遠程實時備份的方式實現binlog備份。
sql
一、基於flush logs方式實現binlog文件切換
數據庫
基本原理:經過last_binlog_pos.txt文件記錄上一次備份的位置點信息,下一次備份基於該位置點信息進行增量備份。若是是首次備份(last_binlog_pos.txt文件不存在,則全量備份binlog);經過flush logs的方式強行切換binlog文件(只備份到次新的binlog文件),避免備份binlog過程當中,MySQL仍對其進行寫入操做;備份每一個binlog文件對其生產側和備份側的binlog文件md5值進行校驗,校驗不經過經過配置重傳次數$num,超太重傳次數仍md5值校驗不經過的話,放棄該binlog備份並記錄到日誌。網絡
腳本以下:tcp
#!/bin/sh ######腳本功能:本地定時備份生產目錄的binlog到備份目錄。##### user="root" password="linzj" port="3306" host="localhost" name=`hostname` last_binlog_dir="/home/mysql/chkpoint" last_binlog_pos="$last_binlog_dir/last_binlog_pos.txt" ###上一次備份的位置點 binlog_backup_dir="/tmp/logbak/$name" ###binlog異地存放目錄 mysqlcommand="mysql -u$user -p$password -h$host -P$port -N --protocol=tcp -e " logdir="/home/mysql/log" binlogfile="$logdir/binlog_bak.log" ###腳本運行日誌存放的目錄必須先行存在,不然後續寫日誌會報日誌文件不存在的問題 if [ ! -d $logdir ] then mkdir -p $logdir fi function create_timestamps() { text=$1 echo "$(date +%Y%m%d-%H:%M:%S):$text" >>$binlogfile } function init_binlog_backup_dir() { ###判斷存放上一次備份位置點的目錄是否存在,不存在就建立 if [ ! -d $last_binlog_dir ] then #echo "$(date +%Y%m%d-%H:%M:%S):last binlog save dir is not existed, now create it !!!">>$binlogfile create_timestamps "last binlog save dir is not existed, now create it !!!" mkdir -p $last_binlog_dir fi ###判斷備份目錄是否存在,不存在就建立 if [ ! -d $binlog_backup_dir ] then #echo "$(date +%Y%m%d-%H:%M:%S):binlog backup dir is not existed, now create it !!!">>$binlogfile create_timestamps "binlog backup dir is not existed, now create it !!!" mkdir -p $binlog_backup_dir fi } function binlog_backup() { ###獲取存放binlog日誌的目錄 binlog_dir=`$mysqlcommand "show variables like 'log_bin_index';" 2>/dev/null|awk '{print "dirname "$2}'|sh` ###獲取binlog日誌的index文件名 binlog_index=`$mysqlcommand "show variables like 'log_bin_index';" 2>/dev/null|awk '{print $2}'` ###獲取binlog日誌的個數信息 binlog_num=`wc -l $binlog_index|awk '{print $1}'` ###若是是首次備份,偏移量binlog_start爲1;若是非首次備份,偏移量binlog_start爲上次偏移量+1。 if [ ! -f "$last_binlog_pos" ] then binlog_start="1" else binlog_last_file=`cat $last_binlog_pos|awk -F \/ '{print $NF}'` binlog_last=`grep -n $binlog_last_file $binlog_index|awk -F \: '{print $1}'` binlog_start=`expr ${binlog_last} + 1 ` fi #echo "binlog_start is $binlog_start" #flush logs,強制切換到新的binlog文件,避免備份當前最新的binlog文件時,mysql仍對其進行寫操做### $mysqlcommand "flush logs" 2>/dev/null for (( i=$binlog_start;i<=$binlog_num;i++ )) do if [ $i == $binlog_num ] then ##記錄當次備份的最後一個binlog文件,做爲本次備份的位置點信息 sed -n "${i}p" $binlog_index > $last_binlog_pos fi cd $binlog_dir logfile=`sed -n "${i}p" $binlog_index|awk '{print "basename "$1}'|sh` num=5 ###重傳次數限制 ###若是拷貝的binlog文件md5值對應不上,嘗試重傳$num次,md5值依然對不上,放棄備份binlog並記錄日誌。 for(( j=1;j<=$num;j++ )) do cp $logfile $binlog_backup_dir md5_source=`md5sum $logfile|awk '{print $1}'` md5_backup=`md5sum $binlog_backup_dir/$logfile|awk '{print $1}'` if [ "$md5_source" = "$md5_backup" ] then gzip $binlog_backup_dir/$logfile echo "$(date +%Y%m%d-%H:%M:%S):$logfile backup to the $binlog_backup_dir sucessfully." >> $binlogfile break fi if [ "$j" == "$num" ] then rm -fr $binlog_backup_dir/$logfile echo "$(date +%Y%m%d-%H:%M:%S):$logfile can not backup to the $binlog_backup_dir sucessfully,please check !!!" >> $binlogfile fi done done } create_timestamps "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" create_timestamps "the binlog backup start now !!!" init_binlog_backup_dir binlog_backup create_timestamps "the binlog backup end now !!!" create_timestamps "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
二、經過mysqlbinlog方式實現遠程異地備份binlog。
ide
基本原理:經過mysqlbinlog的--read-from-remote-server、 --stop-never參數實現異地binlog實時備份。經過while死循環的方式,避免因爲網絡等異常形成的斷連。日誌
腳本以下:
server
#!/bin/sh BACKUP_BIN="mysqlbinlog" LOCAL_BACKUP_DIR="/mysqlbackup/logbak/mysql2/" ###異地存放binlog的目錄 BACKUP_LOG="/home/mysql/log/binlog_log" REMOTE_HOST="192.168.124.132" REMOTE_PORT="3306" REMOTE_USER="root" REMOTE_PASS="linzj" MYSQLCOMMAND="mysql -u$REMOTE_USER -p$REMOTE_PASS -P$REMOTE_PORT --protocol=tcp -N -e " FIRST_BINLOG=$($MYSQLCOMMAND "show binary logs" 2>/dev/null|head -1|awk '{print $1}') ###獲取當前數據庫最老的binlog if [ ! $FIRST_BINLOG ] then echo "沒法獲取binlog信息,請檢查數據庫賬號權限和當前數據庫是否打開binlog日誌" exit fi #time to wait before reconnecting after failure SLEEP_SECONDS=10 ##create local_backup_dir if necessary mkdir -p ${LOCAL_BACKUP_DIR} cd ${LOCAL_BACKUP_DIR} ## 運行while循環,鏈接斷開後等待指定時間,從新鏈接 while : do if [ `ls -A "${LOCAL_BACKUP_DIR}" |wc -l` -eq 0 ];then LAST_FILE=${FIRST_BINLOG} else LAST_FILE=`ls -l ${LOCAL_BACKUP_DIR} | tail -n 1 |awk '{print $9}'` fi ${BACKUP_BIN} --raw --read-from-remote-server --stop-never --host=${REMOTE_HOST} --port=${REMOTE_PORT} --user=${REMOTE_USER} --password=${REMOTE_PASS} ${LAST_FILE} echo "`date +"%Y/%m/%d %H:%M:%S"` mysqlbinlog中止,返回代碼:$?" | tee -a ${BACKUP_LOG} echo "${SLEEP_SECONDS}秒後再次鏈接並繼續備份" | tee -a ${BACKUP_LOG} sleep ${SLEEP_SECONDS} done
綜上所述,這兩種binlog備份的方式各有優缺點:ip
缺點:md5
第一種方式,必須經過定時調度的方式實現備份,極端狀況下存在丟失binlog的可能(在兩個定時調度的窗口時間,MySQL異常而且全部生產binlog不可用,這個窗口時間產生的binlog沒法備份到)。
第二種方式,經過mysqlbinlog的功能去實現實時備份,沒法確認備份的可用性,即沒法經過對比文件md5值來判斷文件是否同生產環境保持一致。極端狀況下會出現異常(網絡異常形成的斷連而且備份路徑的binlog被誤操做),由於斷連是經過while死循環去實現重連的,而重連的位置點信息是基於備份路徑下的最新binlog文件。
優勢:
第一種方式,能夠經過驗證md5值的方式確保備份同生產的一致性。備份的邏輯簡單,便於理解。
第二種方式,能夠實現binlog實時備份功能。
因此,基於以上的優缺點分析,選擇哪一種備份策略,仍須要根據生產環境的實際須要進行抉擇。