數據導出不徹底等於數據備份:java
- 數據導出是指將數據庫中的數據逆向成SQL語句進行導出,因此導出的是SQL文件。一般用做把數據從一個系統遷移到另外一個系統,目的是屏蔽系統之間的差別性
- 數據備份是指將數據庫中數據存儲的相關文件進行拷貝,用於保存一個數據庫的所有物理數據,因此備份後的數據與本來數據在細節及狀態上都是徹底一致的。不會像SQL那樣在使用了一些函數的狀況下,可能會在不一樣的時間點或不一樣的系統上產生不同的結果
冷備份與熱備份:node
- 冷備份:在數據庫已經關閉的狀況下,對數據的備份稱做冷備份
- 熱備份:與冷備份相反,在數據庫節點不停機的狀態下進行的備份被稱做熱備份
冷備份的限制:mysql
- 數據庫必須停機備份,這對一些線上數據庫是沒法接受的
- 備份的數據文件很是佔用存儲空間,而且不支持增量備份
- 冷備份是備份全部的數據文件和日誌文件,因此沒法單獨備份某個邏輯庫和數據表
聯機冷備份:spring
單節點的數據庫在冷備份時須要停機,這就會對業務系統產生影響。爲了解決這個問題,咱們能夠組建集羣而後挑選集羣中的一個節點進行停機冷備份。因爲集羣中還有其餘節點在運行,因此沒必要擔憂影響正在運行的系統。等備份結束以後再啓動該節點,這樣就能解決停機備份帶來的影響sql
熱備份的限制:shell
- 數據庫在熱備份的時候會全局加讀鎖,備份期間節點只能讀取數據不能寫入數據
聯機熱備份:數據庫
一樣的方式,爲了不全局加鎖,咱們能夠挑選集羣中的一個節點與其餘節點解除數據同步關係後進行熱備份。等待備份完成後,再去恢復與集羣中其餘節點的數據同步關係。這樣在備份過程當中就只有該節點會加讀鎖,其餘節點不會受到影響編程
聯機熱備份與聯機冷備份該如何選擇:bootstrap
建議選擇聯機熱備份,由於熱備份能夠選擇全量備份或增量備份。而冷備份只能選擇全量備份,當後期數據量很大的時候,冷備份須要耗費不少的時間,而且因爲是全量備份也須要佔用更多的存儲空間。熱備份只有在第一次備份的時候須要選擇全量備份,後續備份只須要增量備份新數據便可。 所以,熱備份在存儲空間的佔用及備份耗費的時間上都優於冷備份vim
上一小節提到了數據備份是指將數據庫中數據存儲的相關文件進行拷貝,而這些文件有不少,因此讓咱們來簡單認識下MySQL中與數據相關的文件。
首先是組成邏輯庫的文件,在MySQL中一個邏輯庫實際由多個文件組成,其結構以下:
OPT
文件:定義字符集和字符集的排序規則,該文件是一個文本文件FRM
文件:這是數據表的定義文件,包含了數據表的結構信息。不管數據表使用的什麼存儲引擎,每個數據表的定義文件必定是FRM
文件ISL
文件:該文件只有建立了表分區纔會出現,它存儲着表分區數據文件所在的路徑MYD
文件:MyISAM的數據文件MYI
文件:MyISAM的索引文件IBD
文件:InnoDB的索引及數據文件,該文件是一個二進制文件FRM
文件在不少狀況下都會被用到,例如數據庫在執行SQL語句以前,先會審查SQL語句中用到的一些字段是否在FRM
文件中定義了。或者數據庫在優化SQL語句時,經過FRM
文件判斷where
子句中的字段是不是主鍵列或索引列等。由於FRM
文件常常會被使用,因此該文件是一個二進制文件
MySQL中的其餘文件:
auto.cnf
文件:該文件存儲MySQL實例的UUID,即server-uuid
,在集羣中能夠做爲節點的惟一標識grastate.dat
文件:該文件保存的是PXC的同步信息gvwstate.dat
文件:該文件保存的是PXC集羣中其餘節點的信息.pem
:該文件存儲的是加解密用的證書和密鑰信息.sock
:套接字文件,用於本地鏈接MySQL.err
:錯誤日誌文件,MySQL全部錯誤信息都會保存在該文件中.pid
:MySQL進程id文件ib_buffer_pool
:InnoDB緩存文件ib_logfile
:InnoDB事務日誌(redo)ibdata
:InnoDB共享表空間文件logbin
:日誌文件(binlog)index
:日誌索引文件ibtmp
:臨時表空間文件數據文件中的碎片是什麼:
MySQL的數據文件一直存在着碎片化問題,MySQL之因此不會自動整理碎片縮減數據文件的體積,是由於這個整理過程是會鎖表的。若是每刪除一條數據就鎖表整理碎片,那麼勢必會對數據表的讀寫形成很大的影響。不過MySQL在寫入新數據時,會優先將其寫入碎片空間,因此數據文件中的碎片空間對平常運行沒有什麼影響。
可是對於數據庫備份這個場景來講,若是數據文件中存在着大量的碎片,就會致使實際有意義的數據沒多少,而數據文件的體積又很大。這對備份來講就很佔用存儲空間和傳輸帶寬,因此在進行備份以前,須要對數據文件的碎片進行一個整理,儘可能縮減數據文件的體積。
MySQL中整理數據文件碎片的SQL語句以下:
alter table ${table_name} engine=InnoDB;
須要注意的是,在執行該SQL以前,記得先將用於備份的數據庫節點的binlog給關掉。避免binlog中記錄了該SQL,致使在節點備份完成恢復到集羣后,其餘節點同步了該SQL出現整個集羣鎖表的狀況。因此須要註釋掉MySQL配置文件中的如下兩個參數,在備份完成後再打開:
# log_bin # log_slave_updates
在前面介紹了一些前置知識後,本小節就逐步演示一下如何實踐聯機冷備份。我這裏事先準備了一個由三個節點組成的PXC集羣:
首先挑選集羣中的任意一個節點做爲備份節點,而後中止該節點:
[root@PXC-Node3 ~]# systemctl stop mysqld
編輯配置文件,註釋binlog相關參數:
[root@PXC-Node3 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf [mysqld] ... #log-bin #log_slave_updates
而後註釋PXC集羣相關參數:
[root@PXC-Node3 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf [mysqld] #wsrep_provider=/usr/lib64/galera3/libgalera_smm.so #wsrep_cluster_address=gcomm://192.168.190.132,192.168.190.133,192.168.190.134 #wsrep_slave_threads=8 #wsrep_log_conflicts #wsrep_cluster_name=pxc-cluster #wsrep_node_name=pxc-node-03 #pxc_strict_mode=DISABLED #wsrep_sst_method=xtrabackup-v2 #wsrep_node_address=192.168.190.134 #wsrep_sst_auth=admin:Abc_123456
修改完畢後,啓動MySQL服務,此時該節點就退出了PXC集羣:
[root@PXC-Node3 ~]# systemctl start mysqld
該節點的數據文件有1.1個G:
[root@PXC-Node3 ~]# du -h /var/lib/* |grep /var/lib/mysql$ 1.1G /var/lib/mysql [root@PXC-Node3 ~]#
本示例中是對test
庫進行備份,因此在進行備份以前,須要對test
庫下全部的表進行碎片整理。因爲表比較多,我這裏編寫了一個簡單的Java程序來實現:
import com.mysql.jdbc.Driver; import java.sql.*; import java.util.ArrayList; /** * 數據表碎片整理 * * @author 01 * @date 2020-01-25 **/ public class CleanFragments { public static void main(String[] args) throws SQLException { DriverManager.registerDriver(new Driver()); String url = "jdbc:mysql://192.168.190.134:3306/test?useSSL=false"; String username = "admin"; String password = "Abc_123456"; try (Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement pst = connection.prepareStatement("show tables;")) { ResultSet resultSet = pst.executeQuery(); ArrayList<String> tableNames = new ArrayList<>(); while (resultSet.next()) { tableNames.add(resultSet.getString(1)); } for (String tableName : tableNames) { if ("t_range_1".equals(tableName)) { continue; } System.out.println("整理 " + tableName + " 表碎片..."); pst.execute("alter table " + tableName + " engine=InnoDB;"); } } System.out.println("整理完畢..."); } }
碎片整理完成後,中止MySQL服務,由於冷備份須要停機:
[root@PXC-Node3 ~]# systemctl stop mysqld
而後就能夠開始備份了,其實備份的過程也很簡單,沒用到啥高大上的特殊技術,就是使用tar
命令將MySQL數據目錄打成一個壓縮包便可。例如我這裏的數據目錄是/var/lib/mysql
,因此執行的命令以下:
# 先進入到/var/lib/目錄下 [root@PXC-Node3 ~]# cd /var/lib/ # 而後對數據目錄進行打包,mysql.tar.gz是打包後的文件名,存放在/home目錄下 [root@PXC-Node3 /var/lib]# tar -zcvf /home/mysql.tar.gz ./mysql
datadir
參數定義的若是建立了表分區,而且將表分區映射到了其餘目錄上,那麼就還須要對錶分區進行打包。例如我這裏有兩個表分區,分別映射到了/mnt/p0/data/
和/mnt/p1/data/
目錄,因此執行的命令以下:
[root@PXC-Node3 ~]# cd /mnt/ [root@PXC-Node3 /mnt]# tar -zcvf /home/p0.tar.gz ./p0/data/ [root@PXC-Node3 /mnt]# tar -zcvf /home/p1.tar.gz ./p1/data/
到此備份完成後,恢復配置文件中所註釋的配置項,而後重啓節點讓該節點從新加入到PXC集羣中便可。因爲沒啥須要特殊說明的,因此這裏就不演示了。
演示瞭如何冷備份後,接下來則演示如何將備份文件冷還原到其餘的PXC節點上。首先將備份文件傳輸到須要還原的節點上,可使用scp
或rsync
命令在Linux系統之間傳輸文件,以下示例:
[root@PXC-Node3 /home]# scp ./mysql.tar.gz 192.168.190.133:/home/mysql.tar.gz [root@PXC-Node3 /home]# scp ./p0.tar.gz 192.168.190.133:/home/p0.tar.gz [root@PXC-Node3 /home]# scp ./p1.tar.gz 192.168.190.133:/home/p1.tar.gz
還原節點接收到的備份文件以下:
[root@PXC-Node2 ~]# cd /home/ [root@PXC-Node2 /home]# ls mysql.tar.gz p0.tar.gz p1.tar.gz [root@PXC-Node2 /home]#
除此以外還須要進行一些準備工做,由於備份節點是存在表分區的,而且映射了相應的數據目錄,若還原節點不存在則須要建立。以下示例:
[root@PXC-Node2 ~]# mkdir /mnt/p0/ [root@PXC-Node2 ~]# mkdir /mnt/p1/
因爲是冷還原,因此和冷備份同樣也須要先中止還原節點:
[root@PXC-Node2 ~]# systemctl stop mysqld
還原MySQL的數據目錄,命令以下:
# 先備份本來的數據目錄,以防萬一 [root@PXC-Node2 ~]# mv /var/lib/mysql /var/lib/mysql-backup # 將壓縮文件解壓到/var/lib/目錄下 [root@PXC-Node2 /home]# tar -zxvf mysql.tar.gz -C /var/lib/
而後是還原表分區數據目錄:
[root@PXC-Node2 /home]# tar -zxvf p0.tar.gz -C /mnt/ [root@PXC-Node2 /home]# tar -zxvf p1.tar.gz -C /mnt/
刪除auto.cnf
文件,否則uuid重複的話,該節點是沒法啓動的:
[root@PXC-Node2 ~]# rm -rf /var/lib/mysql/auto.cnf
若是你是使用PXC集羣中的首節點做爲備份節點,那麼就還須要將grastate.dat
文件中的safe_to_bootstrap
參數修改成0,普通節點則不須要。以下示例:
[root@PXC-Node2 ~]# vim /var/lib/mysql/grastate.dat ... safe_to_bootstrap: 0
到此就算是還原完成了,啓動MySQL服務便可:
[root@PXC-Node2 ~]# systemctl start mysqld
剩下就是自行驗證下該節點的數據是否正確還原了,可否與集羣中其餘節點進行數據同步等。以及最後清理掉以前備份的舊數據目錄:
[root@PXC-Node2 ~]# rm -rf /var/lib/mysql-backup
冷備份的實際用途:
通過以上小節,如今咱們已經瞭解了冷備份和冷還原,從本節開始咱們來學習熱備份。熱備份是數據庫運行的狀態下備份數據,也是難度最大的備份。PXC集羣常見的熱備份有LVM和XtraBackup兩種方案。
利用Linux的LVM技術來實現熱備份,將MySQL的數據目錄放到LVM邏輯捲上,而後經過LVM快照技術備份邏輯卷的內容。第一次備份是全量備份,以後的備份都是增量備份。在還原時,將快照中的數據目錄恢復到ySQL的數據目錄便可。
使用LVM這種技術不只能夠備份MySQL還能夠備份MongoDB等其餘數據庫,但使用LVM作熱備份方案也比較麻煩,由於須要手動建立邏輯卷、遷移數據目錄、建立快照以及給數據庫加鎖等等,因此LVM並非經常使用的熱備份方案。
由於LVM的麻煩,因此人們都但願使用專業的工具去作熱備份,這個工具就是XtraBackup。XtraBackup是由Percona開源的免費數據庫熱備份工具,它能對InnoDB數據庫和XtraDB存儲引擎的數據庫非阻塞地備份。由於XtraBackup在備份過程當中不會打斷正在執行的事務,而事務日誌中記錄了哪些是備份前寫入的數據哪些是備份後寫入的數據,因此無需加鎖。
另外,XtraBackup提供了對備份數據的壓縮功能,能夠節約備份文件佔用的磁盤空間及網絡帶寬。但XtraBackup在備份使用MyISAM做爲存儲引擎的表時會加讀鎖,即表中的數據可讀但不可寫,不過這也不是問題,以前提到了可使用聯機熱備份的方式來解決加讀鎖的問題。一樣,XtraBackup支持全量備份和增量備份,由於XtraBackup的方便性,因此通常都是採用XtraBackup來作熱備份方案。
系統中一般會同時存在全量備份和增量備份,以防其中一個備份出了問題,還有另外一個備份可使用。因爲全量熱備份比較耗時,因此通常不會常常執行,會間隔一段時間才執行一次。例如,每月一號零點執行或每週一零點執行等。
在Linux中有一個crontab
命令,能夠在固定的間隔時間執行指定的系統指令或shell腳本。使用crontab
命令結合shell腳本能夠實現定時的全量熱備份。
這裏就舉例演示一下,首先編寫執行全量熱備份的shell腳本以下:
[root@PXC-Node3 ~]# vim full-backup.sh #!/bin/bash time=`date "+%Y-%m-%d %H:%M:%S"` echo '執行全量熱備份 '$time innobackupex --defaults-file=/etc/my.cnf --host=192.168.190.134 --user=admin --password=Abc_123456 --port=3306 --no-timestamp --stream=xbstream --encrypt=AES256 --encrypt-threads=10 --encrypt-chunk-size 512 --encrypt-key='1K!cNoq&RUfQsY&&LAczTjco' -> /home/backup/fullBackupOfMysql.xbstream
賦予該腳本執行權限:
[root@PXC-Node3 ~]# chmod -R 777 full-backup.sh
最後配置一下crontab
便可,例如我這裏定義每週一零點執行,這樣就實現了定時全量熱備份:
[root@PXC-Node3 ~]# crontab -e # 每週一零點執行 0 0 * * 1 /root/full-backup.sh > /home/backup/full-backup.log 2>&1
上面介紹了全量熱備份後,咱們來看下如何將XtraBackup備份的文件進行還原。在還原這塊只能冷還原,不存在熱還原,由於對一個正在運行中的數據庫進行在線還原操做,而同時用戶又在讀寫數據,這就有可能致使數據互相覆蓋,使得數據庫的數據發生錯亂。
所以,還原這塊就只能是冷還原,以前也介紹過冷還原,只不過使用XtraBackup進行冷還原會更加簡單,沒有還原冷備份時那麼麻煩。
首先關閉MySQL服務:
[root@PXC-Node3 ~]# systemctl stop mysqld
清空數據目錄及表分區的數據目錄:
[root@PXC-Node3 ~]# rm -rf /var/lib/mysql/* [root@PXC-Node3 ~]# rm -rf /mnt/p0/data/* [root@PXC-Node3 ~]# rm -rf /mnt/p1/data/*
rm
刪除了,若是是實際的運行環境,建議先使用mv
重命名須要刪除的目錄,最後還原完備份文件並驗證沒有問題後,再使用rm
刪除,以免刪庫跑路的悲劇發生備份文件是通過壓縮的,因此須要建立一個臨時目錄來存放解壓後的文件:
[root@PXC-Node3 ~]# mkdir /home/backup/temp
而後使用xbstream
命令將備份文件解壓至該目錄下:
[root@PXC-Node3 ~]# xbstream -x < /home/backup/fullBackupOfMysql.xbstream -C /home/backup/temp/
由於備份文件時進行了加密,因此解壓後的文件都是加密的,須要解密備份文件:
[root@PXC-Node3 ~]# innobackupex --decrypt=AES256 --encrypt-key='1K!cNoq\&RUfQsY\&\&LAczTjco' /home/backup/temp
&
是特殊字符,因此須要使用\
轉義一下因爲是熱備份,因此事務日誌中可能會存在一些未完成的事務,這就須要回滾沒有提交的事務,以及同步已經提交的事務到數據文件。執行以下命令:
[root@PXC-Node3 ~]# innobackupex --apply-log /home/backup/temp
完成以上步驟後,就可使用如下命令對備份文件進行還原:
[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back /home/backup/temp
接着給還原後的目錄文件賦予mysql
用戶權限:
[root@PXC-Node3 ~]# chown -R mysql:mysql /var/lib/mysql/*
到此爲止就完成了冷還原,最後啓動MySQL服務並自行驗證下數據是否正常便可:
[root@PXC-Node3 ~]# systemctl start mysqld
增量熱備份必須以全量熱備份爲基礎進行備份,因此在瞭解了XtraBackup的全量熱備份和全量冷還原後,接下來就能夠實踐XtraBackup的增量熱備份了。
注意事項:
以前演示冷還原的時候已經對全量備份的文件進行了解壓縮和內容解密,因此這裏以/home/backup/temp/
備份目錄爲例,增量熱備份命令以下:
[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --host=192.168.190.134 --user=admin --password=Abc_123456 --port=3306 --incremental-basedir=/home/backup/temp/ --incremental /home/backup/increment
--incremental-basedir
:指定全量備份文件所存儲的目錄,即基於哪一個全量備份進行增量備份--incremental
:指定採用增量備份/home/backup/increment
:增量備份文件所存放的目錄增量備份的文件目錄以下:
[root@PXC-Node3 ~]# ls /home/backup/increment/ 2020-01-26_17-02-21 [root@PXC-Node3 ~]# ls /home/backup/increment/2020-01-26_17-32-41/ backup-my.cnf ibdata1.delta mysql sys tpcc xtrabackup_checkpoints xtrabackup_logfile ib_buffer_pool ibdata1.meta performance_schema test xtrabackup_binlog_info xtrabackup_info [root@PXC-Node3 ~]#
可使用du
命令對比一下全量熱備份與增量熱備份的目錄大小:
[root@PXC-Node3 ~]# du -sh /home/backup/temp/ 1.6G /home/backup/temp/ # 全量熱備份的目錄大小 [root@PXC-Node3 ~]# du -sh /home/backup/increment/2020-01-26_17-32-41/ 92M /home/backup/increment/2020-01-26_17-32-41/ # 增量熱備份的目錄大小 [root@PXC-Node3 ~]#
以後的第二次增量備份就能夠不基於全量備份,而是基於第一次的增量備份,以下示例:
[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --user=admin --password=Abc_123456 --incremental-basedir=/home/backup/increment/2020-01-26_17-32-41/ --incremental /home/backup/increment
若是增量備份時須要使用流式壓縮和內容加密,則添加相關參數便可。以下示例:
[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --user=admin --password=Abc_123456 --incremental-basedir=/home/backup/increment/2020-01-26_17-32-41/ --incremental --stream=xbstream --encrypt=AES256 --encrypt-threads=10 --encrypt-chunk-size 512 --encrypt-key='1K!cNoq&RUfQsY&&LAczTjco' ./ > /home/backup/increment
./
表示將增量備份全部的內容都寫到流式壓縮文件裏,壓縮文件則存放在/home/backup/increment
目錄下一般咱們會讓增量熱備份做爲定時任務自動進行,從而避免人工定點去操做,以節省沒必要要的工做量。在全量熱備份時介紹了使用Linux的crontab
命令來實現shell腳本的定時執行,而一些主流的編程語言也都基本具有實現定時任務的框架或類庫。
這裏以Java爲例,在Java的生態中,有Quartz和Spring框架能夠實現定時任務,一樣也是使用Cron表達式語法。但Java的Cron表達式能夠精確到秒,這一點與Linux的Cron表達式有所不一樣。
因爲Quartz稍微複雜些,爲了簡單起見這裏就以Spring爲例。首先建立一個Spring Boot工程,pom.xml
中的依賴項以下:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
在引導類上添加@EnableScheduling
註解,以開啓定時調度功能:
@EnableScheduling @SpringBootApplication public class IncrementBackupApplication { ... }
在Linux上建立一個文件,用於記錄每次增量熱備份時基於哪一個目錄去備份。例如在第一次增量熱備份時是基於全量熱備份的目錄進行備份的,而在這以後的增量熱備份則是基於上一次增量熱備份的目錄進行備份:
[root@PXC-Node3 ~]# echo '/home/backup/temp/' > /home/backup/increment-backup.cnf
而後編寫實現定時執行增量熱備份的Java類:
package com.example.incrementbackup.task; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.io.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; /** * 增量熱備份定時任務 * * @author 01 * @date 2020-01-26 **/ @Slf4j @Component public class IncrementBackupTask { /** * 每分鐘執行一次增量熱備份 * 固然實際狀況不會設置這麼短的間隔時間 */ @Scheduled(cron = "0 */1 * * * *") public void backup() { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm_ss"); String folderName = LocalDateTime.now().format(formatter); String configPath = "/home/backup/increment-backup.cnf"; try (FileReader fileReader = new FileReader(configPath); BufferedReader bufferedReader = new BufferedReader(fileReader)) { String basedir = bufferedReader.readLine(); String cmd = getCmd(basedir, folderName); log.info("開始進行增量熱備份. 執行的命令:{}", cmd); // 執行增量熱備份命令 Process process = Runtime.getRuntime().exec(cmd); // 等待命令執行完成 process.waitFor(); try (FileWriter fileWriter = new FileWriter(configPath); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { // 更新下次增量備份所使用的basedir路徑 bufferedWriter.write("/home/backup/increment/" + folderName); log.info("增量熱備份結束"); } } catch (IOException | InterruptedException e) { log.error("", e); } } /** * 拼裝 innobackupex 命令參數 */ private String getCmd(String basedir, String folderName) { String cmd = "innobackupex --defaults-file=/etc/my.cnf " + "--user=admin --password=Abc_123456 " + "--incremental-basedir=%s --no-timestamp " + "--incremental /home/backup/increment/%s"; return String.format(cmd, basedir, folderName); } }
完成以上代碼的編寫後,使用maven
將項目打成jar包,而後將該jar包上傳到Linux中,經過java -jar
命令執行。以下:
[root@PXC-Node3 ~]# java -jar increment-backup-0.0.1-SNAPSHOT.jar
執行過程當中輸出的日誌信息以下:
等待備份結束後,能夠看到increment-backup.cnf
文件的內容也更新了:
[root@PXC-Node3 ~]# cat /home/backup/increment-backup.cnf /home/backup/increment/2020-01-26_21_06_00 [root@PXC-Node3 ~]#
生成的備份目錄結構也是正常的:
[root@PXC-Node3 ~]# ls /home/backup/increment/2020-01-26_21_12_00 backup-my.cnf ibdata1.delta mysql sys tpcc xtrabackup_checkpoints xtrabackup_logfile ib_buffer_pool ibdata1.meta performance_schema test xtrabackup_binlog_info xtrabackup_info [root@PXC-Node3 ~]#
到此爲止,咱們就使用Java語言實現了定時增量熱備份數據庫。之因此介紹如何使用編程語言來實現,是由於實際企業應用中,可能會有一些較爲複雜或個性化的需求,單純使用shell腳本是沒法實現的。例如要求備份完成後發送郵件或短信通知相關人員,又或者要求能夠在UI上控制定時執行的間隔時間等等。這種需求都得使用編程語言去定製化開發才能實現。
通過以上小節能夠得知增量熱備份僅備份新數據,而且生成的備份目錄體積也要比全量熱備份生成的目錄體積要小不少。那麼XtraBackup要如何將增量備份的數據還原到數據庫呢?其實也很簡單,就是先將增量熱備份的數據與全量熱備份的數據合併,而後基於合併後的備份數據去還原便可。
增量熱備份能夠有不少個備份點,由於除第一次增量熱備份外,其他的增量熱備份都是基於上一次增量熱備份進行的。因此在還原的時候也能夠選擇任意一個備份點去還原,但事務日誌的處理步驟與全量冷還原不同。
在以前演示全量冷還原的時候,有一個處理事務日誌的步驟,一樣增量冷還原也有這個步驟,可是有些差別。上面提到增量熱備份是能夠有多個備份點的,那麼在還原某一個備份點時就須要處理該備份點及其以前備份點的事務日誌,不然就會出現數據混亂的狀況。以下圖,有三個備份點:
例如,當還原「增量備份1」時,須要先處理其前一個備份點的事務日誌,即圖中的「全量熱備份」。接着再處理「增量備份1」這個備份點的事務日誌,而後合併「增量備份1」的數據到「全量熱備份」中。這樣才能保證多個備份點合併到全量備份點後的數據是一致的,最後還原「全量熱備份」中的數據便可。
再例如,要還原的是「增量備份2」,那麼就得先處理「全量熱備份」,而後處理「增量備份1」,接着處理「增量備份2」,按從前日後的順序依次將這三個備份點的事務日誌都給處理了後,才能合併備份點的數據到全量備份中,最後還原「全量熱備份」中的數據。其他則以此類推......
接下來實操一下增量冷還原,這裏有三個與上圖對應的備份點目錄:
/home/backup/temp/ # 全量熱備份 /home/backup/increment/2020-01-27_10-11-24/ # 增量備份1 /home/backup/increment/2020-01-27_10-15-11/ # 增量備份2
由於是冷還原,因此得先關閉MySQL服務:
[root@PXC-Node3 ~]# systemctl stop mysqld
在本例中要還原的是「增量備份2」這個備份點的數據,按照以前的說明,首先處理全量備份點的事務日誌,執行以下命令:
[root@PXC-Node3 ~]# innobackupex --apply-log --redo-only /home/backup/temp/
--redo-only
:指定不回滾未提交的事務,由於下個備份點的事務日誌裏可能會提交該備份點未提交的事務。若是回滾了就會致使下個備份點沒法正常提交而後處理「增量備份1」的事務日誌,並將"增量備份1"的數據合併到全量備份點上:
[root@PXC-Node3 ~]# innobackupex --apply-log --redo-only /home/backup/temp/ --incremental-dir=/home/backup/increment/2020-01-27_10-11-24/
--incremental-dir
:指定要合併到全量備份的增量備份目錄接着處理「增量備份2」的事務日誌,並將"增量備份2"的數據合併到全量備份點上。因爲只還原到「增量備份2」這個備份點,因此就不須要加上--redo-only
參數了,由於沒有下個備份點了:
[root@PXC-Node3 ~]# innobackupex --apply-log /home/backup/temp/ --incremental-dir=/home/backup/increment/2020-01-27_10-15-11/
與全量冷還原同樣,也需清空數據目錄及表分區的數據目錄:
[root@PXC-Node3 ~]# rm -rf /var/lib/mysql/* [root@PXC-Node3 ~]# rm -rf /mnt/p0/data/* [root@PXC-Node3 ~]# rm -rf /mnt/p1/data/*
完成以上步驟後,就可使用以下命令完成備份文件的還原了:
[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back /home/backup/temp/ # 注意這裏指定的是全量備份點的目錄
接着給還原後的目錄文件賦予mysql
用戶權限:
[root@PXC-Node3 ~]# chown -R mysql:mysql /var/lib/mysql/* [root@PXC-Node3 ~]# chown -R mysql:mysql /mnt/p0/data/* [root@PXC-Node3 ~]# chown -R mysql:mysql /mnt/p1/data/*
到此爲止還原就完成了,最後啓動MySQL服務並自行驗證下數據是否正常便可:
[root@PXC-Node3 ~]# systemctl start mysqld