關於物理備份工具xtrabackup的一些說明能夠先看以前寫過的文章說明:XtraBackup 安裝使用和xtrabackup 使用說明(續),本篇文章將介紹xtrabackup在使用中的注意事項和如何全量、增量備份和恢復,包含TokuDB的備份(感謝吳總的推薦)。因爲物理備份消耗的空間比較大,因此在工做中一直使用mydumper進行備份,經過邏輯備份雖然空間使用上又很大改善,可是因爲還原的時候須要消耗很長時間才能使用,也很是使人頭疼。如今準備在生產環境中使用XtraBackup,記錄使用中的一些注意事項。
php
環境:html
XtraBackup版本爲:2.4 系統版本:14.04、16.04 MySQL版本:5.7.16
說明:由於生產環境中有使用到TokuDB引擎,而Percona版本的XtraBackup不支持對TokuDB的備份,因此不能使用官方的版本。不過有人基於官方版本進行了修改,支持Tokudb的備份,下載地址:https://github.com/XeLabs/tokudb-xtrabackup,做者是BohuTANG。編譯安裝過程:python
① 下載:mysql
git clone https://github.com/XeLabs/tokudb-xtrabackup.git
② 安裝依賴包:git
apt-get install build-essential flex bison automake autoconf \ libtool cmake libaio-dev mysql-client libncurses-dev zlib1g-dev \ libgcrypt11-dev libev-dev libcurl4-gnutls-dev vim-common
③ 編譯安裝github
#程序目錄 mkidr /usr/local/xtrabackup_dir/ #編譯 cd tokudb-xtrabackup cmake . -DBUILD_CONFIG=xtrabackup_release -DWITH_BOOST=extra/boost/boost_1_59_0.tar.gz -DWITH_MAN_PAGES=OFF -DCMAKE_INSTALL_PREFIX=/usr/local/xtrabackup_dir/ make VERBOSE=1 make -j8 #安裝 make install
安裝成功以後,文件裏的信息以下:算法
/usr/local/xtrabackup_dir/bin# ls -lh 總用量 200M lrwxrwxrwx 1 root root 10 8月 21 11:51 innobackupex -> xtrabackup -rwxr-xr-x 1 root root 5.2M 8月 21 11:22 xbcloud -rwxr-xr-x 1 root root 3.0K 8月 21 11:17 xbcloud_osenv -rwxr-xr-x 1 root root 5.0M 8月 21 11:22 xbcrypt -rwxr-xr-x 1 root root 5.1M 8月 21 11:22 xbstream -rwxr-xr-x 1 root root 185M 8月 21 11:32 xtrabackup
由於包含了一些符號信息和調試信息,xtrabackup文件很大,經過strip進行剝離:sql
strip xtrabackup
限制:shell
對於上面編譯好的XtraBackup,對於備份TokuDB引擎有個限制,即不能指定tokudb_data_dir變量,必須使用默認參數。而且MySQL5.7也已經把TokuDB文件放入到對應的數據庫文件夾中。
備份策略:數據庫
.每週日進行全量備份,週一至週六進行基於全量備份的增量備份。這樣即便還原週四的備份,也只要prepare全量和週四增量的備份便可,不須要把週四以前的增量所有apply。
.備份文件不存本地,直接遠程保存到備份服務器。
.備份一個從庫,還原完成直接當從庫來使用。
環境:
MySQL A服務器(備份)
XtraBackup B備份服務器
MySQL C服務器(還原)
MySQL配置文件中配置目錄的相關參數:日誌文件(error log、binlog)最好別放數據目錄裏。
innodb_undo_directory = /var/lib/mysql/undolog/
tokudb_log_dir = /var/lib/mysql/tokudb_log
注意:三臺服務器上最好都裝上XtraBackup,而且A和C的MySQL的配置文件配置的目錄須要一致,如:undolog目錄、tokudb目錄等。關於備份相關的命令能夠看以前寫的文章,本文的備份命令以下:
1)全量備份,每週日進行
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --safe-slave-backup --ftwrl-wait-query-type=all --history --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/"
解釋:經過實際狀況指定須要的參數,壓縮加密打包到遠程服務器,並在遠程服務器解包到指定的目錄。
--defaults-extra-file :該選項指定了在標準defaults-file以前從哪一個額外的文件讀取MySQL配置,必須在命令行的第一個選項的位置。通常用於存備份用戶的用戶名和密碼的配置文件。 --datadir :backup的源目錄,mysql實例的數據目錄。從my.cnf中讀取,或者命令行指定。 --host:該選項表示備份數據庫的地址。 --no-timestamp:該選項能夠表示不要建立一個時間戳目錄來存儲備份,指定到本身想要的備份文件夾。 --slave-info:該選項表示對slave進行備份的時候使用,打印出master的名字和binlog pos,一樣將這些信息以change 。master的命令寫入xtrabackup_slave_info文件。 --safe-slave-backup:該選項表示爲保證一致性複製狀態,這個選項中止SQL線程而且等到show status中的slave_open_temp_tables爲0的時候開始備份,若是沒有打開臨時表,bakcup會馬上開始,不然SQL線程將關閉直到沒有打開的臨時表。若是slave_open_temp_tables在--safe-slave-backup-timeount(默認300秒)秒以後不爲0,從庫sql線程會在備份完成的時候重啓。 --ftwrl-wait-query-type:該選項表示得到全局鎖以前容許那種查詢完成,默認是ALL,可選update。 --history:該選項表示percona server 的備份歷史記錄在percona_schema.xtrabackup_history表。 --backup:建立備份而且放入--target-dir目錄中。 --parallel:指定備份時拷貝多個數據文件併發的進程數,默認值爲1。 --compress:該選項表示壓縮innodb數據文件的備份。 --compress-threads:該選項表示並行壓縮worker線程的數量。 --stream:該選項表示流式備份的格式,backup完成以後以指定格式到STDOUT,目前只支持tar和xbstream。 --encrypt:該選項表示經過ENCRYPTION_ALGORITHM的算法加密innodb數據文件的備份,目前支持的算法有ASE128,AES192,AES256。 --encrypt-threads:該選項表示並行加密的worker線程數量。 --encryption-key-file:該選項表示文件必須是一個簡單二進制或者文本文件,加密key可經過如下命令行命令生成:openssl rand -base64 24。
在備份中,備份帳號和密碼存放在/etc/mysql/xtrabackup.cnf中,格式爲:
[client] user=xtrabackup password=xtrabackup
生成加密key:
openssl rand -base64 24 echo -n "5V05Dm+aFiRxZ6+sjfplK0K2YlbOplZn" > keyfile
該備份帳號的權限:
>show grants for xtrabackup@localhost; +-------------------------------------------------------------------------------------------------------------------------+ | Grants for xtrabackup@localhost | +-------------------------------------------------------------------------------------------------------------------------+ | GRANT CREATE, RELOAD, PROCESS, SUPER, LOCK TABLES, REPLICATION CLIENT, CREATE TABLESPACE ON *.* TO 'xtrabackup'@'localhost' | | GRANT SELECT, INSERT, CREATE ON `PERCONA_SCHEMA`.* TO 'xtrabackup'@'localhost' | +-------------------------------------------------------------------------------------------------------------------------+
2)增量備份:每週一至週六執行
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --safe-slave-backup --ftwrl-wait-query-type=all --history --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=NUM | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/1/
解釋:
--incremental-lsn:該選項表示指定增量備份的LSN,與--incremental選項一塊兒使用。
由於增量備份是根據全量備份(target_dir)來進行的,因爲全量已經傳輸到備份服務器,本地不存備份,因此須要經過記錄當時全量備份時候的LSN,再基於此LSN進行增量備份。
備份信息說明
1:由於從庫開了多線程複製(slave_parallel_workers),但沒開啓GTID,而XtraBackup要求2者必須都開啓,不然報錯:
The --slave-info option requires GTID enabled for a multi-threaded slave.
因此在備份腳本里進行了設置:備份開始前先設置成單線程複製,結束以後設置成多線程;也能夠直接開啓GTID。
2:因爲開啓了--safe-slave-backup參數,在必定時間裏(--safe-slave-backup-timeout),默認300秒,若slave_open_temp_tables參數大於0則會暫停Slave的SQL線程,等待到沒有打開的臨時表的時候開始備份,備份結束後SQL線程會自動啓動。要是備份時間比較長,少不了報警短信的騷擾。由於我在還原該備份完成以後,會對其進行主從一致性檢驗,就關閉了該參數進行備份。最終備份的命令以下:
1)全量備份
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/"
2)增量備份
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=NUM | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/1/
注意:編譯的xtrabackup只支持TokuDB的全量備份,不支持增量備份。
爲了方便,把備份命令放到python裏面去執行,定製成一個備份腳本:(備份服務器B上先建立好目錄。MySQL A服務器上再執行腳本)
MySQL A服務器上的腳本:
#!/usr/bin/env python #-*- encoding:utf-8 -*- import os import sys import time import datetime import smtplib import subprocess import re import MySQLdb from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.Utils import COMMASPACE, formatdate reload(sys) sys.setdefaultencoding('utf8') RETRIES = 1 def retry_times(func): def wrapped(*args, **kwargs): global RETRIES try: return func(*args, **kwargs) except Exception, err: #重試次數 if RETRIES <= 10: print "\n郵件發送重試第【%s】次\n" %RETRIES RETRIES += 1 time.sleep(1) if RETRIES == 10: print "\n重試10次,郵件發送失敗,exit...\n" sys.exit() return wrapped(*args, **kwargs) return wrapped @retry_times def send_mail(to, subject, text, from_mail, server="localhost"): message = MIMEMultipart() message['From'] = from_mail message['To'] = COMMASPACE.join(to) message['Date'] = formatdate(localtime=True) message['Subject'] = subject message.attach(MIMEText(text,_charset='utf-8')) smtp = smtplib.SMTP(server,timeout=3) smtp.sendmail(from_mail, to, message.as_string()) smtp.close() def getDate(): today = datetime.datetime.now().strftime('%Y-%m-%d') weekday = datetime.datetime.now().weekday() return today,weekday def getMonDay(num): monday = (datetime.date.today() - datetime.timedelta(days=num)).strftime("%Y-%m-%d") return monday def getTime(): now = datetime.datetime.now().strftime('%H:%M:%S') return now def getPath(): Path = os.path.realpath(os.path.dirname(__file__)) return Path def setSingleThread(conn): queries = '''\ STOP SLAVE;\ START SLAVE UNTIL SQL_AFTER_MTS_GAPS;\ SET @@GLOBAL.slave_parallel_workers = 0;\ START SLAVE SQL_THREAD\ ''' for query in queries.split(';'): cursor = conn.cursor() # print query time.sleep(0.5) cursor.execute(query) def setMultiThread(conn): queries = '''\ STOP SLAVE;\ START SLAVE UNTIL SQL_AFTER_MTS_GAPS;\ SET @@GLOBAL.slave_parallel_workers = 4;\ START SLAVE SQL_THREAD\ ''' for query in queries.split(';'): cursor = conn.cursor() # print query time.sleep(0.5) cursor.execute(query) def run_cmd(cmd): p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ret_str = p.stdout.read() retval = p.wait() return ret_str if __name__ == "__main__": CWD = '/etc/mysql' db_conf = os.path.join(CWD, 'xtrabackup.cnf') conn = MySQLdb.connect(read_default_file=db_conf,host='localhost',port=3306,charset='utf8') instance_name = 'Job' local_host = 'localhost' remote_host = 'C' today,weekday = getDate() weekday = weekday + 1 print "\n\n\n\n\n備份執行日期是:%s, 星期%s\n" %(today,weekday) # today = '2017-08-20' # weekday = 7 if weekday == 7: setSingleThread(conn) print("\033[0;32m set single thread replication sucess... \033[0m") remote_backupfile = '/data/dbbackup_dir/job/%s/full_backup' %today print remote_backupfile print("\033[0;32m execute full backup... \033[0m") #--safe-slave-backup --safe-slave-backup-timeout=600 xtrabackup_fullbackup = '''/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=%s --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh %s "/usr/local/xtrabackup_dir/bin/xbstream -x -C %s" ''' %(local_host,remote_host,remote_backupfile) print "\n執行全量備份的命令:\n%s\n" %xtrabackup_fullbackup res = run_cmd(xtrabackup_fullbackup) print res setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") if res.find('completed OK!') > 0: _point = re.compile(ur'.*(xtrabackup: The latest check point \(for incremental\): )\'([0-9]+\.?[0-9]*)\'*') incremental_point = dict(_point.findall(res)).get('xtrabackup: The latest check point (for incremental): ') f = open(os.path.join(getPath(),'incremental_point.txt'),'w') f.write(incremental_point) f.close() if incremental_point: subject = '%s【%s】全量物理備份成功' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy") else : subject = '%s【%s】全量物理備份獲取lsn失敗' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy") else : subject = '%s【%s】全量物理備份失敗' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy") else : setSingleThread(conn) print("\033[0;32m set single thread replication sucess... \033[0m") print("\033[0;32m execute incremental backup... \033[0m") monday = getMonDay(weekday) remote_backupfile = '/data/dbbackup_dir/job/%s/%s' %(monday,weekday) # print remote_backupfile try: f = open(os.path.join(getPath(),'incremental_point.txt'),'r') incremental_point = f.read() f.close() except Exception,e: incremental_point = None print e if incremental_point: #--safe-slave-backup --safe-slave-backup-timeout=600 xtrabackup_incrbackup = '''/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=%s --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=%s | ssh %s "/usr/local/xtrabackup_dir/bin/xbstream -x -C %s"''' %(local_host,incremental_point,remote_host,remote_backupfile) print "\n執行增量備份的命令:\n%s\n" %xtrabackup_incrbackup res = run_cmd(xtrabackup_incrbackup) print res setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") if res.find('completed OK!') > 0: subject = '%s【%s】增量物理備份成功' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy") else : subject = '%s【%s】增量物理備份失敗' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy") else : setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") subject = '%s【%s】增量物理備份獲取lsn失敗' %(today,instance_name) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), str(e) , "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy")
備份服務器B上的腳本:
#!/usr/bin/env python #-*- encoding:utf-8 -*- import os import sys import time import datetime import commands def getDate(): today = datetime.datetime.now().strftime('%Y-%m-%d') weekday = datetime.datetime.now().weekday() return today,weekday def mkdir(path): isExists=os.path.exists(path) if not isExists: os.makedirs(path) print "建立成功!" else: print "文件夾存在!" if __name__ == "__main__": today,weekday = getDate() weekday = weekday + 1 # print today,weekday if weekday == 7: # today = '2017-08-20' backup_path = '/data/dbbackup_dir/' instsance_names = ['test','test1','test2'] dir_names = ['full_backup','1','2','3','4','5','6'] for instsance_name in instsance_names: for dir_name in dir_names: dir_path = os.path.join(backup_path,instsance_name,today,dir_name) mkdir(dir_path) else : print "只在週日執行..."
模擬全量備份,備份流程原理的信息以下:
1):fork 一個子線程進行redo log 的複製 2):主線程進行ibd文件複製,直到ibd文件複製完 3):SET GLOBAL tokudb_checkpoint_lock=ON,它的做用是容許拿到checkpoint鎖,此時TokuDB的checkpoint會一直block到該鎖釋放(執行前要把tokudb_checkpoint_on_flush_logs關掉),目的是防止拷貝TokuDB數據文件的過程當中作sharp checkpoint(注意:因爲不作checkpoint,TokuDB的日誌文件會逐漸增多),從而致使數據文件內部不一致(已拷貝的文件被修改) 4):LOCK TABLES FOR BACKUP 1.禁止非innodb表更新 2.禁止全部表的ddl 優化點: 1.不會關閉表 2.不會堵塞innodb表的讀取和更新,對於業務表所有是innodb的狀況,則備份過程當中DML徹底不受損。 5):開始並完成備份非InnoDB表和文件 6):LOCK BINLOG FOR BACKUP,獲取一致性位點 1.禁止對位點更新的操做 2.容許DDl和更新,直到寫binlog爲止。 7):FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS,寫binlog,不輪詢。 8):開始和完成備份TokuDB的undo和redo 9):記錄LSN最後的點,中止redo log的線程的備份 10):解鎖binlog和tables 11):開始和完成備份TokuDB文件 12):SET GLOBAL tokudb_checkpoint_lock=OFF,解鎖TokuDB的checkpoint鎖。
增量備份則讀取全量備份時候記錄的點位進行備份(腳本里把點位寫入到了文件中)。備份服務器的目錄以下:
# du -sch 2017-08-20/* 4.0K 2017-08-20/1 4.0K 2017-08-20/2 4.0K 2017-08-20/3 4.0K 2017-08-20/4 4.0K 2017-08-20/5 4.0K 2017-08-20/6 33G 2017-08-20/full_backup 33G total
到此,備份大體的流程已經介紹完畢,那麼接着繼續介紹如何還原。
由於經過上面的備份腳本已經把備份文件傳輸到了備份服務器B中,後面的相關操做只要在備份服務器B和MySQL服務器C中進行。
1)從備份服務器B中,把備份傳到MySQL服務器C中。如備份目錄爲full_backup
scp -r full_backup/ C:/data/dbbackup_dir/
2)在MySQL服務器C中進行解密、解壓和prepare。解密的key須要和上面加密時候生成的key保持一致!解壓須要安裝qpress。
#解密: for i in `find . -iname "*\.xbcrypt"`; do /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-file=/data/keyfile --encrypt-algo=AES256 < $i > $(dirname $i)/$(basename $i .xbcrypt) && rm $i; done #解壓 for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f $(dirname $f) && rm -f $f; done #prepare,須要執行2次,第1次回滾未提交和執行已提交的事務,第2次生成redo log,加快mysql啓動時間。 /usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
備份文件說明:
root@db-test-xt:/data/dbbackup_dir/full_backup# ls -lh xtrabackup_* -rw-r--r-- 1 root root 27 Aug 22 10:28 xtrabackup_binlog_info -rw-r--r-- 1 root root 27 Aug 22 10:28 xtrabackup_binlog_pos_innodb -rw-r--r-- 1 root root 121 Aug 22 10:28 xtrabackup_checkpoints -rw-r--r-- 1 root root 687 Aug 22 10:27 xtrabackup_info -rw-r--r-- 1 root root 8.0M Aug 22 10:28 xtrabackup_logfile -rw-r--r-- 1 root root 83 Aug 22 10:24 xtrabackup_slave_info
xtrabackup_binlog_info:記錄備份時的binlog點位,如有MyISAM存儲引擎,以該點位準。
xtrabackup_binlog_pos_innodb:記錄備份時的binlog點位,用於InnoDB、XtraDB的點位記錄。
xtrabackup_checkpoints:記錄備份模式(backup_type)以及放備份的起始位置beginlsn和結束位置endlsn等。
xtrabackup_slave_info:備份從庫時記錄的CHANGE信息。
xtrabackup_info:備份的具體信息,如備份命令、版本、開始結束時間、是否壓縮、加密等信息。
通過上面的解密、解壓、prepare以後,數據庫的文件已經生成,如今須要作的就是把這些文件放到MySQL數據目錄中。
3)還原,複製文件
注意:備份和還原的MySQL配置文件所配置的目錄須要保持一致,如:undolog是否獨立,tokudb必須不能指定目錄,保證備份和還原MySQL目錄的一致性。若是起來當一個歷來服務則須要修改server_id。
1:複製文件到數據目錄 /data/dbbackup_dir# mv full_backup/* /var/lib/mysql/ 2:根據配置文件設置目錄 /var/lib/mysql# mkdir undolog /var/lib/mysql# mv undo00* undolog/ 3:修改權限 /var/lib# chown -R mysql.mysql mysql/ 4:肯定好目錄沒問題以後,就能夠直接開啓MySQL
若是MySQL已經正常啓動,只須要執行start slave,不須要change就能夠直接成爲一個從服務。若是擔憂主從數據的一致性問題,能夠經過主從一致性檢驗來保證。
上面已經模擬進行了週日全量備份,如今模擬在上面的全量基礎上進行的增量備份。在進行全量備份時的LSN已經寫入到了文件incremental_point.txt中,該文件和備份腳本在同一級目錄。
仍是和全量備份同樣,執行上面給出的定製備份腳本,如執行時間是週二,執行完後備份服務器的目錄以下:
# du -sch 2017-08-20/* 4.0K 2017-08-20/1 8.2G 2017-08-20/2 4.0K 2017-08-20/3 4.0K 2017-08-20/4 4.0K 2017-08-20/5 4.0K 2017-08-20/6 33G 2017-08-20/full_backup 41G total
能夠看到增量備份目錄是2,這裏須要注意的是:真正的增量實際上是對InnoDB的增量,而MyISAM和TokuDB仍是直接拷貝文件的全量數據。能夠經過增量備份打印出來的信息或則看增量備份的MyISAM、TokuDB的數據文件看出。
增量備份的備份流程和全量備份同樣,能夠直接看全量備份的說明便可,那麼接着繼續介紹如何進行增量+全量的還原。
由於經過上面的備份腳本已經把備份文件傳輸到了備份服務器B中,後面的相關操做只要在備份服務器B和MySQL服務器C中進行。
1)從備份服務器B中,把備份傳到MySQL服務器C中。如備份目錄爲2
scp -r 2/ C:/data/dbbackup_dir/
2)在MySQL服務器C中進行解密、解壓和prepare。解密的key須要和上面加密時候生成的key保持一致!解壓須要安裝qpress。
#解密:在full_backup和2目錄裏執行 for i in `find . -iname "*\.xbcrypt"`; do /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-file=/data/keyfile --encrypt-algo=AES256 < $i > $(dirname $i)/$(basename $i .xbcrypt) && rm $i; done #解壓:在full_backup和2目錄裏執行 for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f $(dirname $f) && rm -f $f; done
#prepare full_backup /usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
這裏須要注意全量備份的元數據中的信息(/data/dbbackup_dir):
# cat full_backup/xtrabackup_checkpoints backup_type = log-applied from_lsn = 0 to_lsn = 370623694056 last_lsn = 370623694065 compact = 0 recover_binlog_info = 0 # cat full_backup/xtrabackup_slave_info CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=48441381;
基於全量備份的增量prepare,能夠先刪除全量備份目錄下的ib_buffer_pool,否則會在prepare增量的時候報錯,不過不影響後續操做。
xtrabackup: Can't create/write to file './ib_buffer_pool' (Errcode: 17 - File exists) [00] error: cannot open the destination stream for /ib_buffer_pool [00] Error: copy_file() failed.
接着應用增量備份
#prepare 2 /usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup --incremental-dir=/data/dbbackup_dir/2
這裏須要注意增量備份中元數據的信息(/data/dbbackup_dir),和全量備份中進行對比:
# cat 2/xtrabackup_checkpoints backup_type = incremental from_lsn = 370623694056 #對應全量備份中的to_lsn to_lsn = 371913526149 last_lsn = 371913526158 compact = 0 recover_binlog_info = 1 # cat 2/xtrabackup_slave_info CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=637921806; #對應的binlog不同
在prepare增量備份期間,能夠看到一些信息:
①:undolog會被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//undo001.delta is 16384 bytes Applying /data/dbbackup_dir/2//undo001.delta to ./undo001...
②:共享表空間被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//ibdata1.delta is 16384 bytes Applying /data/dbbackup_dir/2//ibdata1.delta to ./ibdata1...
③:ibd文件被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//test/test.ibd.delta is 16384 bytes Applying /data/dbbackup_dir/2//test/test.ibd.delta to ./test/test.ibd...
④:frm、MYI、MYD被全量複製,如:
170822 14:04:51 [01] Copying /data/dbbackup_dir/2/test/test.frm to ./test/test.frm 170822 14:04:51 [01] ...done
⑤:沒有看到TokuDB的增量和全量追加和複製,並且增量perpare完以後,全量備份裏的tokudb文件被刪除。
到這裏增量備份已經prepare完成了,此時全量備份裏的一些元數據文件已經被修改:
# cat full_backup/xtrabackup_checkpoints backup_type = full-prepared from_lsn = 0 to_lsn = 371913526149 #已經把增量放進來了 last_lsn = 371913526158 compact = 0 recover_binlog_info = 0 # cat full_backup/xtrabackup_slave_info CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=637921806; #更新成增量的信息
由於不支持TokuDB的增量,並且因爲進行增量的prepare,致使全量備份裏的tokudb文件被刪除,因此須要手動進行復制TokuDB文件。從增量備份裏複製tokudb相關的全部文件到全量備份,如:
/data/dbbackup_dir# mv 2/test/*tokudb full_backup/test/
/data/dbbackup_dir# mv 2/tokudb_log/* full_backup/tokudb_log/ /data/dbbackup_dir# mv 2/tokudb.directory full_backup/ /data/dbbackup_dir# mv 2/tokudb.environment full_backup/ /data/dbbackup_dir# mv 2/__tokudb_lock_dont_delete_me_data full_backup/ /data/dbbackup_dir# mv 2/tokudb.rollback full_backup/
要是不肯定那些庫有TokuDB引擎,能夠經過下面的命令來查看和複製,來替換mv xxx/*.tokudb
#在增量備份裏執行 /data/dbbackup_dir/2#for i in `find . -iname "*\.tokudb"`; do echo "mv $i ../full_backup/"$dirname $i; done | awk -F "/ ./" '{print $1"/"$2}'
最後再次prepare全量備份,生成redo log:
/usr/local/xtrabackup_dir/bin/xtrabackup --prepare --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
到此已經生成了還原所須要的全部文件,只須要把這些文件放到數據目錄便可。
3)還原,複製文件
注意:備份和還原的MySQL配置文件所配置的目錄須要保持一致,如:undolog是否獨立,tokudb必須不能指定目錄,保證備份和還原MySQL目錄的一致性。若是起來當一個歷來服務則須要修改server_id。
1:複製文件到數據目錄
/data/dbbackup_dir# mv full_backup/* /var/lib/mysql/
2:根據配置文件設置目錄
/var/lib/mysql# mkdir undolog
/var/lib/mysql# mv undo00* undolog/
3:修改權限
/var/lib# chown -R mysql.mysql mysql/
4:肯定好目錄沒問題以後,就能夠直接開啓MySQL
若是MySQL已經正常啓動,只須要執行start slave,不須要change就能夠直接成爲一個從服務。若是擔憂主從數據的一致性問題,能夠經過主從一致性檢驗來保證。後續若是遇到什麼「坑」,會持續更新。
如何處理一張表的還原呢?由於XtraBackup是整個實例還原的,因此對於還原恢復單個表的操做能夠這樣操做(必須開啓innodb_file_per_table),用下面的方法替換原有的prepare方法,只須要執行一次便可:
xtrabackup --prepare --export --target-dir=/data/dbbackup_dir/full_backup
用export方法,執行完後,數據庫目錄下的表文件格式會試這樣:
test.cfg #包含了Innodb字典dump test.exp test.frm test.ibd
單表恢復還原:
1:先在MySQL裏discard該表空間 mysql> alter table test discard tablespace; 2:在備份目錄裏把須要的表文件複製到數據庫目錄下 上述的cfg、ibd、frm、exp的表文件複製過去 cp ... ... 3:最後在MySQL裏import該表空間 mysql> alter table test import tablespace; 4:驗證
到此,關於XtraBackup的全量、增量備份還原已經介紹完,總的來講:想要進行物理備份而且有TokuDB引擎,官方的版本不支持,須要使用BohuTANG改版過的XtraBackup,兼容官方版本。而且主要注意下面的狀況:
1:不能設置tokudb_data_dir; 2:不能自動的增量備份TokuDB,須要手動的複製Tokudb文件。 3:備份和還原的MySQL大版本保持一致,並且設置目錄的參數也要同樣。 4:儘可能不要使用MyISAM,用InnoDB替換MyISAM,減小鎖表時間。
5:加密的keyfile必需要和解密的keyfile一致。
備份相關命令總結:
1:普通全量備份 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --target-dir=/data/3306 2:壓縮全量備份:qpress xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --target-dir=/data/3306 3:壓縮加密全量備份 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306 4:打包壓縮加密全量備份: xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306/ > /data/3306/all_db.xbstream 5:打包壓縮加密傳輸到遠程服務器,並在遠程服務器解包 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306/ | ssh 172.16.109.133 "xbstream -x -C /data/" #解包 xbstream -x < all_db.xbstream #解密 for i in `find . -iname "*\.xbcrypt"`; do /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-file=/data/keyfile --encrypt-algo=AES256 < $i > $(dirname $i)/$(basename $i .xbcrypt) && rm $i; done #解壓 for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f $(dirname $f) && rm -f $f; done #apply xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/3306