MariaDB/MySQL備份恢復系列:
備份和恢復(一):mysqldump工具用法詳述
備份和恢復(二):導入、導出表數據
備份和恢復(三):xtrabackup用法和原理詳述
xtrabackup是percona團隊研發的備份工具,比MySQL官方的ibbackup的功能還要多。支持myisam溫全備、innodb熱全備和溫增備,還可以實現innodb的定時點恢復,而且備份和恢復的速度都較快。在目前MySQL的備份實現上,考慮價格、速度、安全、一致性等角度,xtrabackup是非常合適的工具。
MariaDB也可以使用percona xtrabackup進行備份,不過MariaDB基於percona xtrabackup開發了它自己的備份工具:MariaDB Backup。它基於xtrabackup開發,所以所用方法基本和xtrabackup相同,只是有些自己的特性。詳細內容見MariaDB Backup官方手冊:https://mariadb.com/kb/en/library/mariadb-backup/
xtrabackup官方手冊:https://www.percona.com/doc/percona-xtrabackup/LATEST/index.html
1.安裝xtrabackup
下載地址:https://www.percona.com/downloads/XtraBackup/LATEST/
rpm倉庫(實際上是percona的倉庫):http://repo.percona.com/release/
清華大學percona源:https://mirrors.tuna.tsinghua.edu.cn/percona/
因為只是一個備份工具,所以沒必要編譯安裝,直接下載它的rpm包即可。但是該rpm包依賴於libev.so.4,該依賴包可以在epel源中找到。
這里安裝的是目前最新版的xtrabackup-24-2.4.11。
cat <<eof>>/etc/yum.repos.d/percona.repo [percona] name = Percona baseurl = https://mirrors.tuna.tsinghua.edu.cn/percona/release/\$releasever/RPMS/\$basearch enabled = 1 gpgcheck = 0 [epel] name=epelrepo baseurl=https://mirrors.aliyun.com/epel/\$releasever/\$basearch gpgcheck=0 enable=1 eof
[root@node1 ~]# yum list all| grep xtraback -i Repository epel is listed more than once in the configuration holland-xtrabackup.noarch 1.0.14-3.el6 epel percona-xtrabackup.x86_64 2.3.10-1.el6 percona percona-xtrabackup-20.x86_64 2.0.8-587.rhel6 percona percona-xtrabackup-20-debuginfo.x86_64 2.0.8-587.rhel6 percona percona-xtrabackup-20-test.x86_64 2.0.8-587.rhel6 percona percona-xtrabackup-21.x86_64 2.1.9-746.rhel6 percona percona-xtrabackup-21-debuginfo.x86_64 2.1.9-746.rhel6 percona percona-xtrabackup-22.x86_64 2.2.13-1.el6 percona percona-xtrabackup-22-debuginfo.x86_64 2.2.13-1.el6 percona percona-xtrabackup-24.x86_64 2.4.11-1.el6 percona percona-xtrabackup-24-debuginfo.x86_64 2.4.11-1.el6 percona percona-xtrabackup-debuginfo.x86_64 2.3.10-1.el6 percona percona-xtrabackup-test.x86_64 2.3.10-1.el6 percona percona-xtrabackup-test-21.x86_64 2.1.9-746.rhel6 percona percona-xtrabackup-test-22.x86_64 2.2.13-1.el6 percona percona-xtrabackup-test-24.x86_64 2.4.11-1.el6 percona [root@node1 ~]# yum -y install percona-xtrabackup-24
裝完xtrabackup后,生成以下幾個工具。
[root@node1 ~]# rpm -ql percona-xtrabackup-24 | grep bin | xargs ls -hl lrwxrwxrwx 1 root root 10 May 8 19:19 /usr/bin/innobackupex -> xtrabackup -rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbcloud -rwxr-xr-x 1 root root 3.0K Apr 19 01:04 /usr/bin/xbcloud_osenv -rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbcrypt -rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbstream -rwxr-xr-x 1 root root 21M Apr 19 01:11 /usr/bin/xtrabackup
- xbcloud和xbcloud_osenv是xtrabackup新的高級特性:雲備份;
- xbcrypt也是新的特性,加密備份集;
- xbstream是xtrabackup的流數據功能,通過流數據功能,可將備份內容打包並傳給管道后的壓縮工具進行壓縮;
- xtrabackup是主程序;
- innobackupex在以前是一個perl腳本,會調用xtrabackup這個二進制工具,從xtrabackup 2.3開始,該工具使用C語言進行了重寫,當前它是xtabackup二進制工具的一個軟連接,但是實際的使用方法卻不同,並且在以后的版本中會刪除該工具。
在本文中,會分別對兩個主程序innobackupex和xtrabackup的備份恢復方法進行詳細的說明,還會在說明過程中盡可能的解釋它們是如何工作的,另外還會介紹它們的一些特殊功能的選項,如流備份選項。
2.備份鎖
一篇不錯的介紹xtrabackup鎖的文章:https://www.percona.com/blog/2014/03/11/introducing-backup-locks-percona-server-2/。
percona Server 5.6+ 支持一種新鎖——backup lock(備份鎖),這種鎖是percona對MySQL的補充,專門為備份而設計。這種鎖在percona Server 5.6+ 有,MariaDB中也有,但是Oracle的MySQL中沒有,至少MySQL 5.7中沒有。
這種鎖用在備份的時候替代 flush tables with read lock 獲取全局鎖,是一種輕量級的全局鎖。它有兩種類型的鎖:備份表鎖和二進制日志鎖。為此新增了3種語法:
lock tables for backup # 申請備份表鎖 lock binlog for backup # 申請二進制日志鎖 unlock binlog # 釋放二進制日志鎖
備份表鎖在全局范圍內只對非innodb表加鎖,所以持有該鎖后無法修改非innodb表,但卻不影響innodb表的DML。當然,因為是全局鎖,所以也會阻塞DDL操作。
二進制日志鎖在全局范圍內鎖定二進制日志,所以會阻塞其他會話修改二進制日志。這樣可以保證能夠獲取到二進制日志中一致性的位置坐標。
3.xtrabackup備份原理說明
不管是使用innobackupex還是xtrabackup工具進行備份和恢復,都有3個步驟:備份(backup)、准備(prepare)、恢復(copy back)。
注意,xtrabackup備份過程中,先備份innodb表,再備份非innodb表。
3.1 備份過程(backup階段)
(1).在啟動xtrabackup時記下LSN並將redo log拷貝到備份目標目錄下的xtrabackup_logfile文件中。由於拷貝需要一定時間,如果在拷貝時間段內有日志寫入,將導致拷貝的日志和MySQL的redo log不一致,所以xtrabackup還有一個后台進程監控着mysql的redo log,每秒監控一次,當MySQL的redo log有變化,該監控進程會立即將變化的內容寫入到xtrabackup_logfile文件,這樣就能保證拷貝走的redo log中記錄了一切變化。但是這也是有風險的,因為redo是輪訓式循環寫入的,如果某一時刻有非常大量的日志寫到redo log中,使得還沒開始復制的日志就被新日志覆蓋了,這樣會日志丟失,並報錯。
(2).拷貝完初始版的redo log后,xtrabackup開始拷貝innodb表的數據文件(即表空間文件.ibd文件和ibdata1)。注意,此時不拷貝innodb的frm文件。
(3).當innodb相關表的數據文件拷貝完成后,xtrabackup開始准備拷貝非innodb的文件。但在拷貝它們之前,要先對非innodb表進行加鎖防止拷貝時有語句修改這些類型的表數據。
對於不支持backup lock的版本,只能通過flush tables with read lock來獲取全局讀鎖,但這樣也同樣會鎖住innodb表,殺傷力太大。所以使用xtrabackup備份Oracle的MySQL,實質上只能實現innodb表的部分時間熱備、部分時間溫備。
對於支持backup lock的版本,xtrabackup通過lock tables for backup獲取輕量級的backup locks來替代flush tables with read lock,因為它只鎖定非innodb表,所以由此實現了innodb表的真正熱備。
(4).當獲取到非innodb表的鎖以后,開始拷貝非innodb表的數據和.frm文件。當這些拷貝完成之后,繼續拷貝其他存儲引擎類型的文件。(實際上,拷貝非innodb表的數據是在獲取backup locks(如果支持)后自動進行的,它們屬於同一個過程)
(5).當拷貝階段完成后,就到了備份的收尾階段。包括獲取二進制日志中一致性位置的坐標點、結束redo log的監控和拷貝、釋放鎖等。
對於不支持backup lock的版本,收尾階段的過程是這樣的:獲取二進制日志的一致性坐標點、結束redo log的監控和拷貝、釋放鎖。
對於支持backup lock的版本,收尾階段的過程是這樣的:先通過lock binlog for bakcup來獲取二進制日志鎖,然后結束redo log的監控和拷貝,再unlock tables釋放表鎖,隨后獲取二進制日志的一致性位置坐標點,最后unlock binlog釋放二進制日志鎖。
(6).如果一切都OK,xtrabackup將以狀態碼0退出。
所以,對是否支持backup lock的版本,xtrabackup備份的時的行為是不一樣的。
backup階段的過程具體如下圖所示:
FTWRL:flush table with read lock;
3.2 准備過程(prepare階段)
由於備份的時候拷貝走的數據文件可能是不一致的,比如監控着MySQL的redo log中在拷貝過程完成后又新的事務提交了,而拷貝走的數據是未提交狀態的,那么就需要對該事務前滾;如果監控到的日志中有事務未提交,那么該事務就需要回滾。
但是如果只備份了myisam表或其他非事務表數據,因為備份階段直接鎖定了這些表,所以不會有不一致的狀態。
xtrabackup有一個"准備"的階段。這個階段的實質就是對備份的innodb數據應用redo log,該回滾的回滾,該前滾的前滾,最終保證xtrabackup_logfile中記錄的redo log已經全部應用到備份數據頁上,並且實現了一致性。當應用結束后,會重寫"xtrabackup_logfile"再次保證該redo log和備份的數據是對應的。
准備過程不需要連接數據庫,該過程可以在任意裝了xtrabackup軟件的機器上進行,之所能實現是因為xtrabackup軟件的內部嵌入了一個簡化的innodb存儲引擎,可以通過它完成日志的應用。
3.3 恢復過程(copy back階段)
xtrabackup的恢復過程實質是將備份的數據文件和結構定義等文件拷貝回MySQL的datadir。同樣可以拷貝到任意機器上。
要求恢復之前MySQL必須是停止運行狀態,且datadir是空目錄,除非恢復的操作是導入表的操作。具體見后文對應的內容。
4.准備實驗環境
創建測試數據庫backuptest,並創建myisam表和innodb表,此處簡單的使用數值輔助表並分別插入1億條數據。
DROP DATABASE IF EXISTS backuptest; CREATE DATABASE backuptest; USE backuptest; # 創建myisam類型的數值輔助表和對應插入數據的存儲過程 CREATE TABLE num_isam(n INT NOT NULL PRIMARY KEY)ENGINE=MYISAM; DELIMITER $$ DROP PROCEDURE IF EXISTS proc_num1$$ CREATE PROCEDURE proc_num1(num INT) BEGIN DECLARE rn INT DEFAULT 1; TRUNCATE TABLE backuptest.num_isam; INSERT INTO backuptest.num_isam VALUES(1); dd: WHILE rn*2 < num DO BEGIN INSERT INTO backuptest.num_isam SELECT rn+n FROM backuptest.num_isam; SET rn = rn*2; END; END WHILE dd; INSERT INTO backuptest.num_isam SELECT n+rn FROM num_isam WHERE n+rn <=num; END;$$ DELIMITER ; # 創建innodb類型的數值輔助表和對應插入數據的存儲過程 CREATE TABLE num_innodb(n INT NOT NULL PRIMARY KEY)ENGINE=INNODB; DELIMITER $$ DROP PROCEDURE IF EXISTS proc_num2$$ CREATE PROCEDURE proc_num2(num INT) BEGIN DECLARE rn INT DEFAULT 1; TRUNCATE TABLE backuptest.num_innodb; INSERT INTO backuptest.num_innodb VALUES(1); dd: WHILE rn*2 < num DO BEGIN INSERT INTO backuptest.num_innodb SELECT rn+n FROM backuptest.num_innodb; SET rn = rn*2; END; END WHILE dd; INSERT INTO backuptest.num_innodb SELECT n+rn FROM backuptest.num_innodb WHERE n+rn <=num; END;$$ DELIMITER ; # 分別向兩個數值輔助表中插入1億條數據, CALL proc_num1(100000000); CALL proc_num2(100000000);
5.innobackupex工具
5.1 innobackupex實現全備份和恢復的過程
(1). 全備
除了給定連接MySQL服務器的連接參數,只需再給定一個目錄即可,該目錄是備份的目標位置。默認xtrabackup連接數據庫的時候從配置文件中去讀取和備份相關的配置,可以使用選項--defaluts-file指定連接時的參數配置文件,但如果指定該選項,該選項只能放在第一個選項位置。
innobackupex --user=root --password=123456 /bakdir/
默認備份的路徑是指定路徑/bakdir下的一個以時間為時間戳的目錄。
[root@xuexi bakdir]# du -sh /bakdir/2017-04-02_07-09-47/* 4.0K /bakdir/2017-04-02_07-09-47/backup-my.cnf 4.0G /bakdir/2017-04-02_07-09-47/backuptest 589M /bakdir/2017-04-02_07-09-47/ibdata1 1.8M /bakdir/2017-04-02_07-09-47/mysql 8.0K /bakdir/2017-04-02_07-09-47/Performance 636K /bakdir/2017-04-02_07-09-47/performance_schema 1008K /bakdir/2017-04-02_07-09-47/world 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_binlog_info 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_checkpoints 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_info 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_logfile
查看該文件目錄中文件和大小,可以看出xtrabackup的行為就是復制了目標數據庫的相關文件,並新建了幾個文件。
其中:
- backup-my.cnf是拷貝過來的配置文件。里面只包含[mysqld]配置片段和備份有關的選項。
-
xtrabackup_binlog_info中記錄的是當前使用的二進制日志文件。
[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_binlog_info mysql-bin.000001 120
-
xtrabackup_checkpoints中記錄了備份的類型是全備還是增備,還有備份的起始、終止LSN號。
[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 7533359841 last_lsn = 7533359841 compact = 0 recover_binlog_info = 0
-
xtrabackup_info中記錄的是備份過程中的一些信息。
[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_info uuid = 66f34974-1730-11e7-9d09-000c299af3f3 name = tool_name = innobackupex tool_command = --user=root --password=... /bakdir/ tool_version = 2.4.6 ibbackup_version = 2.4.6 server_version = 5.6.35-log start_time = 2017-04-02 07:09:47 end_time = 2017-04-02 07:10:31 lock_time = 0 binlog_pos = filename 'mysql-bin.000001', position '120' innodb_from_lsn = 0 innodb_to_lsn = 7533359841 partial = N # N表示未啟用該方面的功能,如此處表示不是備份部分數據庫或表 incremental = N format = file compact = N compressed = N encrypted = N
-
xtrabackup_logfile是復制和監控后寫的redo日志。該日志是備份后下一個操作"准備"的關鍵。只有通過它才能實現數據一致性。
(2). 全備的准備過程
在全備份完成之后,備份的數據中如果有innodb數據,則還不能用來恢復。因為從xtrabackup開始備份的時候就監控着MySQL的redo log,在拷貝的innodb數據文件中很可能還有未提交的事務,並且拷貝完innodb數據之后還可能提交了事務或者開啟了新的事務等等。總之,全備之后的狀態不一定是一致的。但是如果只備份了myisam表或其他非事務表數據,因為備份階段直接鎖定了這些表,所以不會有不一致的狀態。
xtrabackup有一個"准備"的階段。這個階段的實質就是對備份的innodb數據應用redo log,該回滾的回滾,該前滾的前滾,最終保證xtrabackup_logfile中記錄的redo log已經全部應用到備份數據頁上,並且實現了一致性。當應用結束后,會重寫"xtrabackup_logfile"再次保證該redo log和備份的數據是對應的。
例如,備份的innodb數據文件中存在未提交的事務,但是在監控到的日志中進行了提交,那么就需要對該事務前滾;如果監控到的日志中有事務未提交,那么該事務就需要回滾。
准備階段使用的模式選項是"--apply-log"。准備階段不會連接MySQL,所以不用指定連接選項如--user等。
[root@xuexi bakdir]# innobackupex --apply-log /bakdir/2017-04-02_07-09-47/
在准備成功時,會在頻幕上輸出如下提示內容:
InnoDB: FTS optimize thread exiting. InnoDB: Starting shutdown... InnoDB: Shutdown completed; log sequence number 7533367063 170402 12:11:23 completed OK!
在准備階段,有一個內存使用量選項"--use-memory",該選項默認值為100M,值越大准備的過程越快。當然,將該值加大的前提是服務器內存夠用。
(3). 全備份的恢復過程
恢復的階段就是向MySQL的datadir拷貝。全備份的恢復要求MySQL必須處於stop狀態,並且datadir必須為空哪怕是和MySQL無關的文件也不能存在,它不會去覆蓋datadir中已存在的內容。否則會提示如下錯誤:
innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7) Original data directory /mydata/data is not empty!
停止mysql並清空datadir。
service mysqld stop rm -rf /mydata/data/*
恢復時使用的模式是"--copy-back",選項后指定要恢復的源備份目錄。恢復時因為不需要連接數據庫,所以不用指定連接選項,如--user等。
[root@xuexi bakdir]# innobackupex --copy-back /bakdir/2017-04-02_07-09-47/ 170402 12:36:09 completed OK!
拷貝完成后,MySQL的datadir的文件的所有者和屬組是innobackupex的調用者,所以需要改回mysql.mysql。
[root@xuexi bakdir]# ll /mydata/data/ total 712736 drwxr-x--- 2 root root 4096 Apr 2 12:36 backuptest -rw-r----- 1 root root 616562688 Apr 2 12:35 ibdata1 -rw-r----- 1 root root 50331648 Apr 2 12:35 ib_logfile0 -rw-r----- 1 root root 50331648 Apr 2 12:35 ib_logfile1 -rw-r----- 1 root root 12582912 Apr 2 12:36 ibtmp1 drwxr-x--- 2 root root 4096 Apr 2 12:36 mysql drwxr-x--- 2 root root 4096 Apr 2 12:35 Performance drwxr-x--- 2 root root 4096 Apr 2 12:36 performance_schema drwxr-x--- 2 root root 4096 Apr 2 12:35 world -rw-r----- 1 root root 23 Apr 2 12:35 xtrabackup_binlog_pos_innodb -rw-r----- 1 root root 494 Apr 2 12:35 xtrabackup_info [root@xuexi bakdir]# chown -R mysql.mysql /mydata/data/*
完成這些之后,就可以啟動MySQL服務器了。可以進入mysql測試backuptest數據庫中的數據是否完整。
5.2 innobackupex實現增量備份和恢復的過程
增量備份依賴於全備份。xtrabackup實現增量備份的原理是通過比較全備份的終點LSN和當前的LSN,增備時將從終點LSN開始一直備份到當前的LSN。在備份時也有redo log的監控線程,對於增備過程中導致LSN增長的操作也會寫入到日志中。
增備的實現依賴於LSN,所以只對innodb有效,對myisam表使用增備時,背后進行的是全備。
(1). 要進行增備,首先要有全備文件。這里重新進行一次全備。
innobackupex --user=root --password=123456 /bakdir/
全備完成后,在/bakdir目錄下生成的全備目錄是2017-04-02_13-26-35。
[root@xuexi ~]# ls /bakdir/2017-04-02_13-26-35/ backup-my.cnf ibdata1 Performance secure_dir xtrabackup_binlog_info xtrabackup_info backuptest mysql performance_schema world xtrabackup_checkpoints xtrabackup_logfile
查看xtrabackup_checkpoints可以得知相關的LSN。
[root@xuexi ~]# cat /bakdir/2017-04-02_13-26-35/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 7533367093 last_lsn = 7533367093 compact = 0 recover_binlog_info = 0
注意:要實現增備,這一次的全備一定不能進行"准備"操作,原因稍后給出。
(2). 進行第一次增備。
假設對示例數據可backuptest中的num_innodb表進行了truncate操作。
mysql> truncate backuptest.num_innodb;
然后再增備。增備時使用"--incremental"選項表示增量備份,增量備份時需要通過"--incremental-basedir=fullback_PATH"指定基於哪個備份集備份,因為是第一次增備,所以要基於完全備份增量集。
[root@xuexi ~]# innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-basedir=/bakdir/2017-04-02_13-26-35/
增備完成后,生成的增備集為/bakdir/2017-04-02_13-39-05/,查看其中的xtrabackup_checkpoints,可以看到備份的起始LSN是上次全備完成后的LSN。
[root@xuexi ~]# cat /bakdir/2017-04-02_13-39-05/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533367093 to_lsn = 7533372535 last_lsn = 7533372535 compact = 0 recover_binlog_info = 0
默認情況下,增備的起始LSN是自動獲取的,但是在某些情況下無法獲取,還有些情況下無法獲取到將要增備的basedir。xtrabackup提供的選項"--incremental-lsn=N"可以顯式指定增備的起始LSN,顯式指定LSN時,可以無需提供增備的basedir。
例如,如果獲取到了上次全備的終止LSN為7533367093,可以如下方式增備:
innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-lsn=7533367093
這樣增備后也在/bakdir中生成一個時間戳目錄/bakdir/2017-04-02_13-50-33。查看LSN信息:
[root@xuexi ~]# cat /bakdir/2017-04-02_13-50-33/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533367093 to_lsn = 7533372535 last_lsn = 7533372535 compact = 0 recover_binlog_info = 0
由此可知和指定--incremental-basedir進行增備是一樣的。
(3). 進行第二次增備。
假設在第一次增備后,向上次truncate的表backuptest.num_innodb表中插入的100W條記錄。
mysql> call backuptest.proc_num2(1000000); mysql> select count(*) from backuptest.num_innodb; +----------+ | count(*) | +----------+ | 1000000 | +----------+
然后進行增備。這次增備是基於第一次增備的(當然也可以基於全備進行備份,這樣實現的是差異備份)。
[root@xuexi ~]# innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-basedir=/bakdir/2017-04-02_13-39-05/
這次增備完成后生成的備份集為/bakdir/2017-04-02_14-03-51/。查看LSN信息:
[root@xuexi ~]# cat /bakdir/2017-04-02_14-03-51/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533372535 to_lsn = 7585150275 last_lsn = 7585150275 compact = 0 recover_binlog_info = 0
(4). 增備的准備過程
增備的准備過程和全備的准備過程有點不一樣,不到最后恢復的時候不能進行任何"准備"過程。
增備過程中的每一次備份行為都會監控MySQL的redo log,寫入到xtrabackup_logfile的日志中可能會有未提交的事務,但是到后面增備的時候進行了提交,也就是說提交過程記錄到了增備時監控的日志xtrabackup_logfile中。如果在增備前進行了"准備",那么該事務就會被回滾,后面增備中的提交就丟失了,由此會造成數據丟失。
要保證將所有的備份集進行整合,需要使用在每個備份集的"准備"過程中使用"--redo-only"選項,這樣應用日志時會"直線向前"直到最后一個備份集。它的本質是向全備集中不斷的追加應用增備中的日志。但是,最后一個增備集需要作為備份集整合的終點,所以它不能使用"--redo-only"選項。整合完成之后,原來的全備就已經完整了,這時再對追加完成的全備集進行一次"准備"即可用於后面的恢復。
所以,如果全備為A,3次增備分別為B/C/D,如果只想恢復到C,那么從A開始整合到C結束即可。
因為在每一個增備的"准備"過程中都需要向整合的開始備份集中追加應用日志,所以每一次增備的"准備"都需要指定整合的開始備份集目錄作為basedir。例如指定全備份作為整合的初始備份集。
從以上實驗過程中,得到的全備集是2017-04-02_13-26-35,第一次和第二次增備集分別是2017-04-02_13-26-35、2017-04-02_14-03-51。下面是它們的"准備"過程。
# 對整合的開始備份集——全備集應用日志,並指定"--redo-only"表示開始進入日志追加 innobackupex --apply-log --redo-only /bakdir/2017-04-02_13-26-35 # 對第一個增備集進行"准備",將其追加到全備集中 innobackupex --apply-log --redo-only /bakdir/2017-04-02_13-26-35 --incremental-dir=/bakdir/2017-04-02_13-39-05 # 對第二個增備集進行"准備",將其追加到全備集中,但是不再應用"--redo-only",表示整合的結束點 innobackupex --apply-log /bakdir/2017-04-02_13-26-35 --incremental-dir=/bakdir/2017-04-02_14-03-51 # 對整合完成的全備集進行一次整體的"准備" innobackupex --apply-log /bakdir/2017-04-02_13-26-35
當所有的備份集整合完畢后,就像是一個完整的全備集,全備中的LSN會更新到整合的結束點。如下:
[root@xuexi data]# cat /bakdir/2017-04-02_13-26-35/xtrabackup_checkpoints backup_type = full-prepared from_lsn = 0 to_lsn = 7585150275 #整合完成后全備中的LSN last_lsn = 7585150275 compact = 0 recover_binlog_info = 0 [root@xuexi data]# cat /bakdir/2017-04-02_14-03-51/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533372535 to_lsn = 7585150275 #整合的結束備份集中的LSN last_lsn = 7585150275 compact = 0 recover_binlog_info = 0
如果不小心整合的順序錯誤了,那么整合的備份集將是無效的,需要重新整合。
(5). 增備的恢復過程
因為整合結束后就等價於一個全備集,所以可以直接進行恢復。
恢復過程同樣需要保證MySQL的datadir是空的,且MySQL服務器是stop的。
service mysqld stop rm -rf /mydata/data/* innobackupex --copy-back /bakdir/2017-04-02_13-26-35 chown -R mysql.mysql /mydata/data/*
然后重啟MySQL,進入查看可知num_innodb的數據為100W行記錄,即恢復成功。
mysql> select count(*) from backuptest.num_innodb; +----------+ | count(*) | +----------+ | 1000000 | +----------+
5.3 innobackupex實現導出和導入單張表的過程
默認情況下,InnoDB表不能通過直接復制表文件的方式在mysql服務器之間進行移植,即便使用了innodb_file_per_table選項。而使用Xtrabackup工具可以實現此種功能,不過只能"導出"具有.ibd文件的表,也就是說導出表的mysql服務器啟用了innodb_file_per_table選項,而且要導出的表還是在啟用該選項之后才創建的。
導入表的是,要求導入表的服務器版本是MySQL 5.6+,且啟用了innodb_file_per_table選項。
(1). 導出表
導出表是在"准備"的過程中進行的,不是在備份的時候導出。對於一個已經備份好的備份集,使用"--apply-log"和"--export"選項即可導出備份集中的表。
假如以全備份集/bakdir/2017-04-02_17-41-38為例,要導出其中的表。
innobackupex --apply-log --export /bakdir/2017-04-02_17-41-38
在導出過程中,會看到如下信息:
xtrabackup: export metadata of table 'backuptest/num_innodb' to file `./backuptest/num_innodb.exp` (1 indexes) xtrabackup: name=PRIMARY, id.low=144, page=3
它說明了創建了一個.exp文件。
查看備份集目錄下的backuptest目錄,會發現多出了2個文件:.cfg和.exp,再加上.ibd文件,這3個文件是后續導入表時所需的文件。
-rw-r--r-- 1 root root 349 Apr 2 18:15 num_innodb.cfg -rw-r----- 1 root root 16K Apr 2 18:15 num_innodb.exp -rw-r----- 1 root root 8.4K Apr 2 17:41 num_innodb.frm -rw-r----- 1 root root 31M Apr 2 17:41 num_innodb.ibd
其中.cfg文件是一種特殊的innodb數據字典文件,它和exp文件的作用是差不多的,只不過后者還支持在xtradb中導入,嚴格地講,要將導出的表導入到MySQL5.6或者percona server 5.6中,".cfg"文件完全可以不需要,但是如果有該文件的話,會進行架構驗證。
(2). 導入表
要在mysql服務器上導入來自於其它服務器的某innodb表,需要先在當前服務器上創建一個跟原表表結構一致的表,而后才能實現將表導入:
mysql> CREATE TABLE tabletest (...) ENGINE=InnoDB;
然后將此表的表空間:
mysql> ALTER TABLE mydatabase.tabletest DISCARD TABLESPACE;
接下來,將來自於"導出"表的的.ibd和.exp文件復制到當前服務器的數據目錄,如果導入目標服務器是MySQL 5.6+,也可以復制.cfg文件。然后使用如下命令將其“導入”:
mysql> ALTER TABLE mydatabase.tabletest IMPORT TABLESPACE;
5.4 innobackupex實現部分備份和恢復的過程
xtrabackup支持部分備份,意味着可以指定備份哪個數據庫或者哪個表。
部分備份只有一點需要注意:在恢復的時候不要通過"--copy-back"的方式拷貝回datadir,而是應該使用導入表的方式。盡管使用拷貝的方式有時候是可行的,但是很多情況下會出現數據庫不一致的狀態。
(1). 備份
創建部分備份有三種方式:
- 通過"--include"選項可以指定正則來匹配要備份的表,這種方式要使用完整對象引用格式,即db_name.tab_name的方式。
- 將要備份的表分行枚舉到一個文件中,通過"--tables-file"指定該文件。
- 或者使用"--databases"指定要備份的數據庫或表,指定備份的表時要使用完整對象引用格式,多個元素使用空格分開。
使用前兩種部分備份方式,只能備份innodb表,不會備份任何myisam,即使指定了也不會備份。而且要備份的表必須有獨立的表空間文件,也就是說必須開啟了innodb_file_per_table,更精確的說,要備份的表是在開啟了innodb_file_per_table選項之后才創建的。第三種備份方式可以備份myisam表。
例如 --include='^back.*[.]num_*' ,將備份back字母開頭的數據庫中num開頭的表,其中"[.]"的中括號不能少,因為正則中"."有特殊意義,所以使用中括號來枚舉以實現對象的完整引用。
innobackupex --user=root --password=123456 --include='^back*[.]num_*' /bakdir/
使用"--include"和"--tables-file"備份后,會生成一個時間戳目錄,目錄中只有和要備份的表有關的文件。
[root@xuexi data]# ls /bakdir/2017-04-02_17-35-46/ backup-my.cnf ibdata1 xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile
如果使用的是--databases選項,則會生成一個時間戳目錄,里面有備份的數據庫代表的目錄,如果只備份了某個表,則該數據庫目錄中只有該表相關的文件。
innobackupex --user=root --password=123456 --databases='mysql.user backuptest' /bakdir/
上面只備份mysql.user表和backuptest數據庫,在生成的時間戳目錄中將有兩個mysql目錄和backuptest目錄。
[root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/ backup-my.cnf backuptest ibdata1 mysql xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile [root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/backuptest/ db.opt num_innodb.frm num_innodb.ibd num_isam.frm num_isam.MYD num_isam.MYI [root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/mysql/ user.frm user.MYD user.MYI
(2). 部分備份的准備和恢復過程
部分備份的准備和恢復過程分別是導出表和導入表的過程。見上文。
5.5 innobackupex實現定時點恢復
xtrabackup本身無法實現定時點恢復,只能通過恢復備份后通過二進制日志實現。實現方法和一般定時點恢復是一樣的。見:二進制日志定點還原數據庫。
5.6 流備份和遠程備份
xtrabackup支持備份流,當前可用的流類型只有tar和xtrabackup自帶的xbstream,通過流可以將它們傳遞給其他程序進行相關的操作,如壓縮。但是不建議在備份的同時進行壓縮,因為壓縮會占用極大的cpu資源,使得備份時間延長很多,溫備的過程也就延長了。
另外,MySQL的數據文件壓縮比非常大,所以建議備份后在空閑的時候進行壓縮。
xtrabackup還支持遠程備份,只需使用"--remote-host"指定遠程的主機名即可,指定方式和ssh指定的方式一樣。如--remote-host=root@192.168.100.18。
使用流備份的方法如下:
# 使用tar流 innobackupex --user=root --password=123456 --stream=tar /bakdir/ >/tmp/a.tar # 使用tar流的同時交給gzip壓縮 innobackupex --user=root --password=123456 --stream=tar /bakdir/ | gzip >/tmp/a.tar.gz # 使用tar流備份到遠程主機中並歸檔 innobackupex --user=root --password=123456 --stream=tar /bakdir/ | ssh root@192.168.100.10 "cat - > /tmp/`date +%F_%H-%M-%S`.tar" # 使用tar流備份到原遠程主機中並解包 innobackupex --user=root --password=123456 --stream=tar /bakdir/ | ssh root@192.168.100.10 "cat - | tar -x -C /tmp/" # 使用xtrabackup自帶的xbstream流 innobackupex --user=root --password=123456 --stream=xbstream /bakdir/ >/tmp/b.xbs # 解壓xbstream流 innobackupex --user=root --password=123456 --stream=xbstream /bakdir/ | ssh root@192.168.100.10 "cat - | xbstream -x -C /tmp/" # 使用xbstream流的同時進行壓縮,使用"--compress"選項 innobackupex --user=root --password=123456 --stream=xbstream --compress /bakdir/ > /bakdir/backup.xbs
注意,如果在解壓備份的.tar.gz時出錯,可能在解壓的時候需要使用-i選項。如tar -xif /tmp/b.tar/gz。
5.7 加速備份
當備份到本地的時候,可以使用"--rsync"選項,該選項用於在flush tables with read lock后調用rsync替代cp進程復制非Innodb數據和.frm文件,加快復制速度。
但要注意,因為支持備份鎖的版本在獲取到backup locks的時候會自動復制非Innodb數據和.frm文件,所以"--rsync"選項是無效的。
另外,該選項不能和"--stream"選項和"--remote-host"選項同時使用。
6.xtrabackup工具
xtrabackup工具是C語言編寫的工具,在innobackupex使用C重寫之后,innobackupex是該工具的一個軟鏈接。但是它不能實現innobackupex的所有功能,例如xtrabackup工具沒有恢復功能,而innobackupex有"--copy-back"選項來恢復。
xtrabackup工具有兩種常用運行模式:"--backup"和"--prepare"。還有兩個比較少用的模式:"--stats"和"--print-param"。
由於前文對innobackupex的介紹非常詳細,xtrabackup在功能實現上和它是一樣的。所以下面將簡單介紹。
6.1 xtrabackup實現全備
(1).備份過程
和innobackupex備份過程不同的是,xtrabackup的備份路徑是由"--target-dir"選項嚴格指定的,如果指定的目錄不存在,它備份的時候不會在target-dir目錄中再創建時間戳子目錄。
[root@xuexi data]# xtrabackup --backup --user=root --password=123456 --datadir=/mydata/data --target-dir=/bakdir/fullback [root@xuexi data]# ls /bakdir/fullback backup-my.cnf ibdata1 Performance secure_dir xtrabackup_binlog_info xtrabackup_info backuptest mysql performance_schema world xtrabackup_checkpoints xtrabackup_logfile
(2).准備過程
xtrabackup --prepare --target-dir=/bakdir/fullback
(3).恢復過程
xtrabackup自身不能恢復,只能通過拷貝備份集的方式來恢復。例如使用rsync或者cp等。
另外,恢復時也一樣要求MySQL是stop狀態,datadir是空目錄。並且拷貝完成后要修改datadir中文件的所有者和屬組為mysql用戶和組。
service mysqld stop rm -rf /mydata/data/* rsync -azP /bakdir/fullback/* /mydata/data chown -R mysql.mysql /mydata/data/*
6.2 xtrabackup實現增備
(1).首先進行全備
xtrabackup --backup --user=root --password=123456 --datadir=/mydata/data --target-dir=/bakdir/base_full
(2).進行第一次增備
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak1 --incremental-basedir=/bakdir/base_full --datadir=/mydata/data/
同樣也可以在增備時使用"--incremental-lsn"來指定從哪個lsn開始增量備份,這和innobackupex是一樣的。
(3).進行第二次增備
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak2 --incremental-basedir=/bakdir/incr_bak1 --datadir=/mydata/data/
(4).准備過程
准備過程和innobackupex是一樣的,使用"--apply-log-only"來直線向前地應用redo log,同樣,在最后一個增備集的准備過程中不能使用"--apply-log-only"選項。
xtrabackup --prepare --apply-log-only --target-dir=/bakdir/base_full xtrabackup --prepare --apply-log-only --target-dir=/bakdir/base_full --incremental-dir=/bakdir/incr_bak1 xtrabackup --prepare --target-dir=/bakdir/base_full --incremental-dir=/bakdir/incr_bak2
(5).恢復階段
恢復階段即拷貝階段,和前面全備的恢復階段是一樣的,要求MySQL停止運行,datadir是空目錄,拷貝全備目錄到datadir,修改datadir的所有者和屬組。
6.3 xtrabackup實現部分備份
xtrabackup部分備份和innobackupex不太一樣,innobackupex的部分備份實質上是在已經備份好的備份集上導出導入表,而xtrabackup直接在備份過程中篩選要備份的目標,它不建立在已有的備份集上。
(1).備份過程
- xtrabackup使用"--tables"選項對應innobackupex的"--include"選項,它們是一樣的,都是正則匹配完整對象引用名稱。
- 使用"--tables-file"選項指定枚舉要備份表的列表,每行一個表,表名需要使用完整對象引用名稱。和innobackupex一樣的。
- 使用"--databases"和"--databases-file"指定要單獨備份的數據庫或表,后者可以枚舉出要備份的列表。這兩個選項不能使用通配符和正則匹配。
例如:
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/part_bak1 --datadir=/mydata/data/ --tables="^back*[.]num_*"
(2).准備過程
xtrabackup的部分備份的准備要比innobackupex方便的多,直接對備份集進行"--prepare"即可。
xtrabackup --prepare --target-dir=/bakdir/part_bak1