如今通用的mysql主從方案已經很成熟,例如,如今公司作的是一主+兩從方案,若是主機宕掉,採用域名方式切換從機,也很是方便。node
如今增長一套方案,實現如下功能:mysql
一、方便的備份可刻盤,或者靈活的備份到第三主機。sql
二、若是出現誤刪除,可恢復。數據庫
第一點是必要的,如出現重大物理災難,例如整個機房癱瘓,刻盤恢復是很重要的,固然這種狀況極低。服務器
設計總體備份圖以下:網絡
備份方案socket
數據庫主機是 ***.***.***.245,***.***.***.246, ***.***.***.39。spa
過程以下:設計
一、39從機會每週執行一次定時腳本database_dump_senior.sh一次,生成dump出一份備份,舉例來講每週日上午10點。每次dump出一份都會記錄當天的日期,並將導出的databases_product.sql和binlog_info.txt文件保存到當前日期下,例如 /home/data/mysql_bak/dumps/2013_08_06/ 下。而後rsync同步到245和246的文件夾下。 日誌
二、245會有定時腳本每隔十分鐘執行一次(能夠按需設定),讀取dumps文件夾下的從機binlog信息,讀取binlog_info.txt裏的日期信息生成日期文件夾,讀取binlog_info.txt文件找到要備份的binglog日誌,cp到binlog文件夾下。如/home/data/mysql_bak/binlog/2013_08_06/下。而後同步一份到246和39
三、39和245都會在每次腳本執行時清除8天未被修改過的數據,這樣能夠保持每臺服務器至少有兩個版本的備份。在網絡斷掉的狀況下是有用處的。
目錄結構
/home/data/mysql_bak/ 下 ------dumps ------2013_08_06 ------databases_product.sql ------ binlog_info.txt ------2013_08_13 ------databases_product.sql ------ binlog_info.txt ------binlog_info.txt ------binlog ------2013_08_06 ------mysql-bin.000385 ------mysql-bin.000386 ------2013_08_13 ------mysql-bin.000386 ------mysql-bin.000387
爲了不轉儲時主機壓力過大,採用在從機備份的方式,39從機在stop slave 後開始 dump一份全庫的備份,而後記錄從機備份的位置,保存在binlog_info.txt裏。binlog_info.txt 保存內容以下:
current_date:2013_08_15
Master_Log_File: mysql-bin.000386
Read_Master_Log_Pos: 90835176
Relay_Log_File: netease-test-namenode-relay-bin.000022
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000386
Exec_Master_Log_Pos: 90835176
Until_Log_File:
Until_Log_Pos: 0
current_date 是由腳本根據系統時間生成,其他是讀取從機變量。
出現風險的情況
一、 從機39壞了,binlog_info.txt未被替換成新的,這時主機會按從原有的binlog_info.txt讀取到的位置信息,一直保存最新的binlog。
二、 主機245壞了,因爲在246和39備份了binlog,能夠將數據恢復精確到到最後十分鐘(主機定時任務時間)。
三、 從機 246 壞了,無任何影響。
四、採用binlog在主機備份是保證數據始終與主機一致,更高的可靠性。
五、經過刪除腳本,保證不管何時都會有兩份備份,一份最新的,一份上週的。
這些都要配合從機狀態監測。
腳本
從機39上跑的腳本:
#!/bin/sh current_date=`date +%Y_%m_%d`; back_path="/home/data/mysql_bak/dumps"; `mkdir -p ${back_path}/${current_date}`; #中止與主機同步 mysql --socket=/home/mysql/data_product/mysql.sock -e "stop slave"; echo "now, slave stopped!"; #導出全部數據庫 echo "dump all databases begin!"; `mysqldump --all-databases --socket=/home/mysql/data_product/mysql.sock > ${back_path}/${current_date}/databases_product.sql`; echo "dump all databases end!"; #保存當前日期 `echo "current_date:${current_date}" > ${back_path}/${current_date}/binlog_info.txt`; #保存如今導出時的binlog位置 `mysql --socket=/home/mysql/data_product/mysql.sock -e "show slave status \G"|egrep 'Log_File|Log_Pos' >> ${back_path}/${current_date}/binlog_info.txt`; #拷貝一份到備份的根目錄 `cp ${back_path}/${current_date}/binlog_info.txt ${back_path}/binlog_info.txt`; #從新開啓與主機同步 mysql --socket=/home/mysql/data_product/mysql.sock -e "start slave"; echo "now, slave started!"; #刪除8天前備份,這樣每次保存最新一份,和最新一份的上一份。 find ${back_path}/ -type f -ctime +8 -exec rm -rf {} \; #刪除空文件夾 find ${back_path}/ -type d -regex ".*/[0-9_]+$"|(while read arg;do if [ `ls $arg |wc -l` -eq 0 ]; then rmdir $arg ; fi; done) echo "old backups has been deleted!"; #將備份binlog位置信息文件,傳送給主庫 rsync -avz --delete ${back_path}/ ***.***.***.245::database_bak/dumps/ rsync -avz --delete ${back_path}/ ***.***.***.246::database_bak/dumps/
主機245上跑的腳本
#!/bin/sh save binlogs #全局變量 back_path="/home/data/mysql_bak"; mysql_path="/home/mysql/data_product"; #判斷若是不存在binlog的備份信息文件,則退出 if [ ! -f "${back_path}/dumps/binlog_info.txt" ];then echo "ERROR,binlog_info.txt not exist,please check your file!"; exit; fi cd ${mysql_path}; #讀取備份binlog位置以及日期信息 echo "now,get the backup binlog position info!" current_date=`cat ${back_path}/dumps/binlog_info.txt|grep 'current_date'|sed 's/current_date://g'|tr ' ' '\0'`; logFile=`cat ${back_path}/dumps/binlog_info.txt |grep 'Relay_Master_Log_File'|sed 's/Relay_Master_Log_File://g'|tr ' ' '\0'`; echo -e "current date is : ${current_date}\nBinlog file is : ${logFile}\n"; #若是不存在則,建立備份文件夾 `mkdir -p ${back_path}/binlog/${current_date}`; #備份記錄binlog文件以後的剩餘binlog文件 cat mysql-bin.index |grep -A100 ${logFile}|sed "s/.\///"|awk -v back_path=${back_path} -v current_date=${current_date} \ '{print "now save:" $0 ;system("cp " $0 " "back_path"/binlog/"current_date"/"$0);}'; echo "backup binlog ended!"; #刪除8天前備份,這樣每次保存最新一份,和最新一份的上一份。 find /home/data/mysql_bak/binlog/ -type f -ctime +8 -exec rm -rf {} \; #刪除空文件夾 find /home/data/mysql_bak/binlog/ -type d -regex ".*/[0-9_]+$"|(while read arg;do if [ `ls $arg |wc -l` -eq 0 ]; then rmdir $arg ; fi; done) echo "old backups has been deleted!"; #將備份binlog信息同步到從庫 rsync -avz --delete ${back_path}/binlog/ ***.***.***.39::database_bak/binlog/ rsync -avz --delete ${back_path}/binlog/ ***.***.***.246::database_bak/binlog/