所謂的數據安全,最容易被人誤覺得是隻有數據丟失,其實還包括數據被脫庫、泄密等方面。mysql
數據庫具有7*24小時提供服務的能力,是數據庫管理員的重要職責。sql
全量數據就是數據庫中全部的數據(或某一個庫的所有數據);全量備份就是把數據庫中全部的數據進行備份。數據庫
備份數據庫中全部庫的全部數據:vim
mysqldump -B --master-data=2 --single-transaction -A |gzip >/opt/all.sql.gz
備份oldboy一個庫中全部數據:安全
mysqldump -B --master-data=2 --single-transaction oldboy |gzip >/opt/oldboy.sql.gz
增量數據就是指上一次全量備份數據以後到下一次全量備份以前數據庫所更新的數據。在使用mysqldump命令作全備時,增量數據就是MySQL的binlog日誌,所以,對binlog日誌的備份在此處就能夠稱爲增量備份,固然,有些工具自己就能夠實現全量以及增量數據備份,例如Xtrabackup。bash
週一00點全量備份 | 週二00點全量備份 | 週三00點全量備份 | ...... |
---|---|---|---|
01.sql.gz | 02.sql.gz | 03.sql.gz | ...... |
週一增量備份 | 週二增量備份 | 週三增量備份 | ...... |
mysql-bin.00002一、...... | mysql-bin.00003五、...... | mysql-bin.00004九、...... | ...... |
按天全備的特色:服務器
一、優勢:恢復數據時須要的數據文件數量少,恢復時間短,維護成本低。 二、缺點:天天一個全備,佔用空間多,佔用系統資源多,常常備份會影響用戶體驗。
中小企業用得最多的策略就是按天全備,而後根據空間狀況保留全備份數,例如僅保留7天內的備份數據,若是企業數據很重要,則可使用磁帶機等設備留存一年以上的備份數據。架構
binlog增量的清理能夠經過在my.cnf中配置「過時清理天數」的相關參數(expire_logs_days=7)來實現,例如保留7天內的binlog日誌,理論上若是天天進行全備,那麼binlog只要保留1天的。app
每週一00點全量備份 | |||
---|---|---|---|
01.sql.gz | |||
週一增量備份 | 週二增量備份 | 週三增量備份 | 一直到下週日增量備份 |
mysql-bin.00002一、...... | mysql-bin.00003五、...... | mysql-bin.00004九、...... | ...... |
按周全備的特色:tcp
一、優勢:每週僅有一個完整備份,所以佔用磁盤總空間小,佔用系統資源少,備份次數少,用戶體驗好一些。 二、缺點:恢復時數據文件多,致使恢復麻煩,維護成本高,恢復時間長。
大型企業因爲數據量特別大,天天全備時間太長,所以有可能會採用周備的策略,這樣不只有利於節省數據存儲空間並且不會影響用戶訪問數據庫的體驗。
MySQL備份的經常使用方式有邏輯備份和物理備份。
MySQL的邏輯備份其實就是使用MySQL自帶的mysqldump命令或其餘相關工具,把MySQL數據以SQL語句的形式導出或備份成文件。在恢復的時候則經過執行mysql恢復命令(或source等)將存儲的SQL語句文件數據還原到MySQL數據庫中。
實現邏輯備份的經常使用工具爲MySQL自帶的mysqldump命令,備份全部庫:
mysqldump -A -B --master-data=2 --single-transaction |gzip >/opt/all.sql.gz
恢復數據庫的方法之一爲:
zcat opt/all.sql.gz|mysql
使用此種邏輯備份方式進行全量備份後的增量數據就是數據庫記錄的binlog日誌文件,那麼,如何增量恢復binlog日誌呢?mysqlbinlog工具能夠把binlog日誌轉換成SQL語句,而後經過mysql恢復命令(或source等)將SQL語句還原到MySQL數據庫中。
恢復增量數據:
mysqlbinlog mysql-bin.000008 mysql-bin.000009 >bin.sql #將binlog文件解析爲SQL語句 mysql <bin.sql #恢復到數據庫
邏輯備份的優勢爲操做簡單、方便、可靠,而且備份的數據能夠跨平臺、跨版本、甚至跨軟件、跨操做系統,還能夠實現分庫分表備份;邏輯備份也有必定的缺點,例如,備份速度比物理備份慢、恢復的效率也不是特別高等。
mysqldump是MySQL官方自帶的最經常使用的邏輯備份工具,還能實現分表分庫備份,還有一個mydumper工具,它是一個在GPL許可下發布的高性能MySQL備份和恢復工具集。
適用於數據量不是特別大的場景,打包前不大於30GB的數據庫數據,30GB的值主要是考慮備份效率的問題,以及管理員使用複雜度的平滑。不過,在跨版本、跨軟件升級或遷移數據的時候,此時物理備份通常就不能使用。
MySQL的物理備份方法之一是使用cp、rsync、tar、scp等複製工具把MySQL數據文件複製成多份,因爲在備份期間數據仍然有寫入操做,因此,直接複製的備份方式會引發數據丟失。另外在恢復數據庫時,對新數據庫的路徑、配置也有要求,通常要和原庫的配置保持一致(版本、路徑、配置儘量同樣)。
爲了確保備份期間數據的一致性,能夠選擇人工停庫或者鎖庫後再進行物理複製,而這在生產環境中通常是不容許的,除非是能夠申請停機或鎖表時間,因此使用傳統Linux命令複製工具仍是比較粗的冷備份方式,應避免使用。
通常在進行大規模數據庫遷移時,先停庫,而後物理遷移,這樣作是頗有效率的方案。
除了在Linux命令行經過命令直接複製MySQL數據文件以外,還有一些其餘的第三方的開源或商業物理熱備份工具,如Xtrabackup。使用這個工具能夠實現物理全備及增量備份。
物理備份的優缺點正好與邏輯備份相反,所以在企業裏應根據需求,互補使用。
一、優勢:速度快,效率高。 二、缺點:不容易跨平臺、跨版本、跨軟件、跨操做系統,能夠實現分庫分表備份,但恢復時會麻煩不少,軟件的使用也比較複雜一些。
Linux下冷備份工具爲cp、tar,備份時須要鎖表或者停庫以確保數據的一致性;開源的熱備份(基於InnoDB)工具則是Xtrabackup。
數據庫總數據量超過30GB的,可以使用Xtrabackup熱備工具進行備份,以提高效率。
能夠選擇在數據庫的從庫上進行備份,備份時中止SQL線程應用數據到數據庫,而後經過cp或tar打包備份,這也是一種不錯的冷備方案,不會影響數據庫的服務。
物理備份與邏輯備份的對比:
邏輯備份 | 物理備份 | |
---|---|---|
備份原理 | 以SQL語句的形式 | 直接複製磁盤物理文件或其餘非SQL語句方式的備份 |
相關命令 | mysqldump、mysql、mysqlbinlog | cp、rsync、tar、scp、Xtrabackup(熱備) |
備份要求 | 須要鎖表但不須要停庫。鎖表會影響數據庫更新,InnoDB引擎能夠不鎖表,而採用事務備份方案 | 冷備須要鎖表或停機,熱備不須要鎖表(僅事務引擎,例如InnoDB)或停機 |
配置特色 | 恢復時與系統版本、庫的配置基本版本無關 | 物理複製須要系統、配置、版本儘量地一致 |
性能特色 | 速度慢 | 速度快 |
方便性考慮 | 安全、易掌握、容易控制,通常不會丟失數據 | 冷備簡單,但應用場景少,熱備工具操做複製一些,較難掌握 |
中小企業通常會採用邏輯備份,經常使用的工具就是mysqldump命令,備份的策略通常是每日進行全量備份,備份會選擇在數據庫業務流量低估時執行,備份時能夠鎖表或者採用事務方式備份。
簡單的備份腳步:
vim bak.sh #!/bin/bash export PATH=/application/mysql/bin:/usr/local/bin:/sbin:/bin:/usr/bin bak_path=/server/backup [ ! -d $bak_path ] && mkdir -p $bak_path #若備份路徑不存在則建立 mysqldump -B -A --master-data=2 |gzip >$bak_path/${file_name}.sql.gz #若是僅爲innodb引擎,則能夠再加上--single-transaction參數 rsync -az $bak_path/ rsync_backup@172.16.1.31::mysql/ --password-file=/etc/rsync.password #備份完成後馬上推送至備份服務器,須要提早部署rsync服務 find $bak_path/ -type -f -name "*.sql.gz" -mtime +7|xargs rm -f #刪除本地的7天備份
稍微複雜點的腳步:
vim bak.sh #!/bin/bash export PATH=/application/mysql/bin:/usr/local/bin:/sbin:/bin:/usr/bin bak_path=/server/backup [ ! -d $bak_path ] && mkdir -p $bak_path #若備份路徑不存在則建立 if [ $(date +%w) -eq 6 ] #若是時間爲週六,則 then file_name=bak_$(date +%w_%F) #將備份文件名改成周和日期,目的是在備份服務器上保留每週六的數據 else file_name=bak_$(date +%F) #不然,備份文件名爲日期 fi mysqldump -B -A --master-data=2 |gzip >$bak_path/${file_name}.sql.gz md5sum $bak_path/${file_name}.sql.gz >$bak_path/${file_name}.flag #作md5指紋的目的是用於將來檢測備份及傳輸結果是否正常 rsync -az $bak_path/ rsync_backup@172.16.1.31::mysql/ --password-file=/etc/rsync.password #備份完成後馬上推送至備份服務器,須要提早部署rsync服務 find $bak_path/ -type -f -name "*.sql.gz" -mtime +7|xargs rm -f #刪除本地的7天備份
配置定時任務,使其每日0點執行腳本:
crontab -e bak mysql for oldboy at 20200515 00 00 * * * /bin/sh /server/scripts/bak.sh &>/dev/null
保留最近7天的全部備份,同時保留每週六的所有備份:
find /server/backup/ -type f -name "bak_*" -mtime +7 ! -name "bak_6*" find /server/backup/ -type f -name "bak_*" -mtime +7 ! -name "bak_6*" |xargs rm -f
使用mysqldump全備的數據何時能夠派上用場:
一、遷移或者升級數據庫時。 二、增長從庫時。 三、人爲執行DDL、DML語句破壞數據庫數據時(此時若使用主從庫就會沒法防止數據丟失,由於全部庫都會執行破壞語句)。 四、跨機房災備時,此時須要將全備份複製到異地。
如果由於硬件或刪除物理文件致使數據庫故障,就不須要用備份數據恢復了,能夠直接把主庫關閉,在從庫上配置好VIP等配置後,啓動從庫提供服務便可。
中小企業增量備份就是備份binlog文件,在MySQL沒有主從複製功能或主從複製功能不完善的時候,咱們就曾採起定時或實時推binlog文件的方法。例如每分鐘推一次binlog到備份服務器上,或者經過mysqlbinlog參數read-from-remote-server,在其餘服務器上遠程讀取binlog。
可是這類方法都不是最佳的,由於有可能會丟失數據。比較好的binlog增量備份或MySQL備份方法就是爲MySQL數據庫配置異機主從複製功能(實時複製功能),即binlog會被實時地發送到從服務器上,這樣效果纔是最好的。固然,也要相應地在主從複製的從庫上實現全備。
當須要完整恢復數據庫數據的時候,就會須要binlog增量恢復。
大多數中小企業的數據庫環境都爲一主多從,所以,可採起在一個從庫服務器上專門作全量以及增量備份(須要開啓從庫記錄binlog日誌功能),至於備份方法,採用mysqldump、Xtrabackup都可。
完整恢復數據庫數據須要具有的條件:
一、具有全量備份(mysqldump)。 二、除全量備份之外,還有全量備份以後產生的全部binlog增量日誌。
模擬0點開始對數據庫oldboy數據進行全備:
mysqldump -B --master-data=2 --single-transaction oldboy|gzip >/data/backup/oldboy_$(date +%F).sql.gz
模擬0點全備後用戶繼續寫入數據:
mysql -e "use oldboy;insert into test values(6,'bingbing');" mysql -e "use oldboy;insert into test values(7,'xiaoting');"
模擬上午10點管理員刪除oldboy數據庫:
mysql -e "drop database oldboy;show databases;"
恢復前準備,移走全部binlog增量文件,防止二次破壞,並確認是否有全備:
cp -a /application/mysql/data/mysql-bin.* /data/backup/
開始恢復:
一、中止數據庫對外訪問。由於是經過drop命令刪除數據庫的,後面不會有寫入操做,所以,能夠不用額外中止寫入。但若是是由於update致使的數據破壞,最好是停庫處理或對外中止寫入。這裏採用iptables防火牆屏蔽全部應用程序的寫入: iptables -I INPUT -p tcp --dport 3306 ! -s 172.16.1.51 -j DROP #非172.16.1.51禁止訪問數據庫3306端口。 二、解壓全備的數據: gzip -cd oldboy_2020-05-19.sql.gz >oldboy.sql 三、解析binlog文件增量數據: sed -n '22p' oldboy.sql 從代碼裏能夠看到,要從mysql-bin.000004文件的7181位置點開始恢復增量數據: mysqlbinlog -d oldboy mysql-bin.000004 --start-position=7181 -r bin.sql 恢復後面的全部binlog文件: mysqlbinlog -d oldboy mysql-bin.000005 mysql-bin.000006 -r bin1.sql 四、剔除誤刪除數據庫的drop語句: grep -w drop bin.sql #過濾drop單詞的行。 sed -i '/drop database oldboy/d' bin.sql #刪除drop數據庫oldboy的語句。 恢復0點之前的全備數據: mysql </data/backup/oldboy.sql #先恢復全備,即0點之前的備份 恢復增量備份: mysql oldboy</data/backup/bin.sql #恢復增量文件
全備命令把2個庫備份成了一個備份文件:
mysqldump -B --master-data=2 --single-transaction oldboy mysql|gzip>/data/backup/all.sql.gz
在還原時,不少時候只須要還原一個庫或者多個庫的一個表,這個時候,整個備份文件就會很難拆分,給恢復也會帶來麻煩。對於這種狀況,最好是分庫分表備份。
最佳的方法就是從數據庫中取出全部庫名,而後對每一個數據庫執行一次備份。
分庫備份的腳本:
vi fenku.sh #!/bin/bash export PATH=/application/mysql/bin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin bak_path=/server/backup/$(date +%F) [ ! -d $bak_path ] && mkdir -p $bak_path for dbname in `mysql -e "show databases"|sed '1,2d'|grep -v _schema` #取庫名輪詢備份 do mysqldump -B --master-data=2 $dbname|gzip >$bak_path/${dbname}_$(date +%F).sql.gz #注意備份的名字 done
分表備份比分庫更細,實際上就是先取一個庫名,而後循環讀取該庫裏的表進行備份,備份完以後,再取下一個庫名,繼續循環庫裏的全部表進行備份,知道全部庫裏的全部表都備份完畢。
分表備份的腳本:
vi fenbiao.sh #!/bin/bash export PATH=/application/mysql/bin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin bak_path=/server/backup/$(date +%F) [ ! -d $bak_path ] && mkdir -p $bak_path for dbname in `mysql -e "show databases"|sed '1,2d'|grep -v _schema` do for tablename in `mysql -e "show tables from $dbname;"|sed '1d'` do mysqldump -B --master-data=2 $dbname$tablename|gzip >$bak_path/${dbname}_${tablename}_$(date +%F).sql.gz done done
在中小公司通常比較經常使用的作法是,每日0點執行全備任務,先把數據按照日期備份到數據庫本地,而後推送到數據庫備份服務器,因爲本地空間有限,所以本地僅保留3-7日的全備。
若是有備用的服務器資源可用,那麼最好經過主從同步的方式進行備份,這樣即便物理機損壞了也能夠很快地切換到新服務器(還能夠HA自動切換),可是主從複製的缺點是不能解決錯誤執行SQL語句的問題。
所以,咱們通常會在某一臺不對外提供業務的從庫上使用mysqldump或Xtrabackup來進行定時備份。這裏有個須要特別注意的地方,用於備份從庫的二進制日誌記錄功能必須打開。