隨着公司業務的不斷擴大,數據量也日益漸漲。往往人們總是覺得一般不會出什么大問題,從而容易忽略數據備份的重要性。以下是我所在環境的數據備份方案場景。大多數公司還是比較喜歡用雲服務器節省資源,當然願意花錢的可以用雲廠商提供的備份工具。擁有獨立IDC的可以使用專業備份設備本地+異地通過光纖備份,效率和安全都是極致的。我現在的環境就是比較尷尬的一種,首先數據庫等業務環境都在雲服務器上,但是雲服務器沒有較大的空間去存儲備份,也不願去采用廠商的備份工具。這就需要我們將備份拉取的本地進行存儲。在此之前他們原有的備份方式是采用破解的MySQL客戶端工具Navicat Premium在本地進行遠程備份,這種方法可以備份,但是存在各種問題。首先你是用的非正版,出了問題你除了百度別無他法,再者這種工具拿來備份的人是極少的,你在百度上搜素也找不到多少相關的文章,所以是一個較大的坑。另一方面根據實際觀察,這玩意在本地進行備份走的是MySQL的公網,且不說備份速度極慢,備份期間長時間占滿MySQL服務器的出網帶寬,這是我們不願看到的現象。
數據備份我們要遵守以下幾點:
1.備份時不能影響業務正常運行,則需要熱備
2.備份效率要高(數據量不大卻要備份四五個小時,這種方式肯定不能要)
3.備份的完整性(我們備份的數據不是仍在存儲里就可以了,它要在出現意外故障的時候能用得上)
4.備份的最小化(存儲也是要花錢的,我們當然需要,備份保留的時間最長,占用的空間越小越好)
1.1拓撲圖
1.2 Xtrabackup介紹
PerconaXtraBackup[A1] 是一個免費的、在線的、開放源碼的、針對MySQL和MySQL的Percona Server所有版本的完整數據庫備份解決方案。PerconaXtraBackup在事務性系統上執行在線非阻塞、嚴格壓縮、高度安全的完全備份,以便應用程序在計划的維護窗口中仍然完全可用。
1.3 備份方式
l 熱備份:讀寫不受影響(mysqldump-->innodb)
l 溫備份:僅可以執行讀操作(mysqldump-->myisam)
l 冷備份:離線備份,讀寫都不可用
l 邏輯備份:將數據導出文本文件中(mysqldump)
l 物理備份:將數據文件拷貝(xtrabackup、mysqlhotcopy)
l 完整備份:備份所有數據
l 增量備份:僅備份上次完整備份或增量備份以來變化的數據
l 差異備份:僅備份上次完整備份以來變化的數據
xtrabackup是一種物理備份工具,通過協議連接到mysql服務端,然后讀取並復制innodb底層的"數據塊",完成所謂的"物理備份"。
1.4 xtrabackup 特點
1、備份過程快速、可靠;
2、備份過程不會打斷正在執行的事務;
3、能夠基於壓縮等功能節約磁盤空間和流量;
4、自動實現備份檢驗;
5、還原速度快;
* 熱備
* 增量
* 差量
Xtrabackup有兩個主要的工具:
l xtrabackup
l innobackupex
1.xtrabackup 是用來備份 InnoDB 表的,不能備份非 InnoDB 表,和 mysqld server 沒有交互;
2.innobackupex 腳本用來備份非 InnoDB 表,同時會調用 xtrabackup 命令來備份 InnoDB 表,還會和 mysqld server 發送命令進行交互,如加讀鎖(FTWRL)、獲取位點(SHOW SLAVE STATUS)等
簡單來說,innobackupex 在 xtrabackup 之上做了一層封裝。
一般情況下,我們是希望能備份 MyISAM 表的,雖然我們可能自己不用 MyISAM 表,但是 mysql 庫下的系統表是 MyISAM 的,因此備份基本都通過 innobackupex 命令進行。
[A1]Facebook是PerconaXtraBackup中增量備份的早期采用者
1.5 備份腳本
1.5.1 數據庫端
#!/bin/sh # #descriptiom: mysql data_back #date: 2020-04-23 #備份主機 db_host='10.0.0.1' #生產:10.0.0.1 #預發布:10.0.0.2 #備份用戶 db_user='root' #密碼 db_pwd='123456789' #生產:123456789 #預發布:123456789 #時間 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date "+%Y-%m-%d"` #備份目錄 db_full='/home/mysql/back/full' db_incremental='/home/mysql/back/incremental' db_local1='/home/mysql/back/full/chkpoint' db_local2='/home/mysql/back/incremental/chkpoint' #數據庫 db_name='test' #生產:test #預發布:test #日志路徑 db_log='/home/mysql/log' ############################ if [ ! -d $db_local1 ] then mkdir -p $db_local1 fi if [ ! -d $db_local2 ] then mkdir -p $db_local2 fi if [ ! -d $db_log ] then mkdir -p $db_log fi ############################ #日志 function log_info () { if [ -d $db_log/dbback ] then touch $db_log/dbback fi DATE_N=`date "+%Y-%m-%d %H:%M:%S"` USER_N=`whoami` echo "${DATE_N} ${USER_N} execute $0 [INFO] $@" >>$db_log/dbback } function log_error (){ DATE_N=`date "+%Y-%m-%d %H:%M:%S"` USER_N=`whoami` echo -e "\033[41;37m ${DATE_N} ${USER_N} execute $0 [ERROR] $@ \033[0m" >>$db_log/dbback } function fn_log () { if [ $? -eq 0 ] then log_info "$@ sucessed." echo -e "\033[32m $@ sucessed. \033[0m" else log_error "$@ failed." echo -e "\033[41;37m $@ failed. \033[0m" exit 1 fi } trap 'fn_log "do not send CTR + C when excute script !!!! "' 2 #全量備份 Full (){ innobackupex --defaults-file=/etc/my.cnf --host=$127.0.0.1 --user=$db_user --password=$db_pwd --databases=$db_name --stream=xbstream --compress --extra-lsndir=$db_local1 $db_full|gzip|ssh root@10.31.233.247 "cat >/worker/db_back/full/$dates1.gz" B_tat=`echo $?` if [ $B_tat -eq 0 ] then B_size=`ssh root@中轉服務器IP "ls -lh /worker/db_back/full"|awk -F "[ ]" '{print $5,$9}'` fn_log "全量備份成功 $B_size" ssh root@中轉服務器IP "ls -lh /worker/db_back/full"|awk -F "[ ]" 'NR==2{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'>>/home/mysql/log/mail.txt mail -s "MySQL data backup" yunwei@163.com </home/mysql/log/mail.txt >/home/mysql/log/mail.txt else fn_log "全量備份失敗" echo "全量備份失敗"|mail -s "MySQL data backup" yunwei@163.com fi } #增量備份 incremental (){ innobackupex --defaults-file=/etc/my.cnf --host=127.0.0.1 --user=$db_user --password=$db_pwd --databases=$db_name --stream=xbstream --compress --incremental --extra-lsndir=db_local1 --incremental-basedir=$db_local1 $db_incremental |gzip|ssh root@10.31.233.247 "cat >/worker/db_back/incremental/$dates1.gz" B_tat1=`echo $?` if [ $B_tat1 -eq 0 ] then B_size1=`ssh root@中轉服務器IP "ls -lh /worker/db_back/incremental"|awk -F "[ ]" '{print $5,$9}'` fn_log "增量備份成功 $B_size1" ssh root@中轉服務器IP "ls -lh /worker/db_back/incremental"|awk -F "[ ]" 'NR==2{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'>>/home/mysql/log/mail.txt mail -s "MySQL data backup" yunwei@163.com </home/mysql/log/mail.txt >/home/mysql/log/mail.txt else fn_log "增量備份失敗" echo "增量備份失敗"|mail -s "MySQL data backup" yunwei@163.com fi } case $1 in Full) Full ;; incremental) incremental ;; *) echo "Please use it this way. Usage:$0 {Full|incremental}" ;; esac
1.5.2 中轉站腳本
[root@ ~]# cd /data/scripts/ [root@ scripts]# ll total 4 -rwxr-xr-x 1 root root 406 May 25 14:31 backup.sh [root@ scripts]# cat backup.sh #!/bin/sh # #descriptiom: mysql databack #date: 2020-05-22 #備份清理 #時間 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date "+%Y-%m-%d"` #備份保留時間(天) Rtime='1' #備份目錄 db_full='/worker/db_back/full' db_incremental='/worker/db_back/incremental' find $db_full -mtime +$Rtime -name "*.gz" -exec rm -rf {} \; find $db_incremental -mtime +$Rtime -name "*.gz" -exec rm -rf {} \;
1.5.3 本地存儲端
#!/bin/sh # #descriptiom: mysql databack #date: 2020-05-22 #備份清理 #時間 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date -d '-1 day' '+%Y-%m-%d'` #備份保留時間(天) Rtime='90' #備份目錄 db_full='/home/mysql/back/full' db_incremental='/home/mysql/back/incremental' if [ ! -d $db_full ] then mkdir -p $db_full fi if [ ! -d $db_incremental ] then mkdir -p $db_incremental fi week=`date +%w` if [ $week -eq 2 ] then sshpass -p 中轉服務器密碼 scp -rp root@中轉服務器外網IP:/worker/db_back/full/$dates1.gz $db_full B_stat=`echo $?` if [ $B_stat -eq 0 ] then B_size=`ls -lh $db_full/$dates1.gz|awk -F "[ ]" 'NR==1{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'` echo "全量備份拉取完成 $B_size"|mail -s "MySQL data backup" yunwei@163.com else echo "全量備份拉取失敗"|mail -s "MySQL data backup" yunwei@163.com fi else sshpass -p 中轉服務器密碼 scp -rp root@中轉服務器外網IP:/worker/db_back/incremental/$dates1.gz $db_incremental B_stat1=`echo $?` if [ $B_stat1 -eq 0 ] then B_size1=`ls -lh $db_incremental/$dates1.gz|awk -F "[ ]" 'NR==1{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'` echo "增量備份拉取完成 $B_size1"|mail -s "MySQL data backup" yunwei@163.com else echo "增量備份拉取失敗"|mail -s "MySQL data backup" yunwei@163.com fi fi find $db_full -mtime +$Rtime -name "*.gz" -exec rm -rf {} \; find $db_incremental -mtime +$Rtime -name "*.gz" -exec rm -rf {} \;