數據庫熱備份神器 - XtraBackup

常見的熱備份方案

LVM方案

利用Linux的LVM技術來實現熱備份,將MySQL的數據目錄放到LVM邏輯捲上,然後通過LVM快照技術備份邏輯卷的內容。第一次備份是全量備份,之後的備份都是增量備份。在還原時,將快照中的數據目錄恢復到ySQL的數據目錄即可。

使用LVM這種技術不僅可以備份MySQL還可以備份MongoDB等其他數據庫,但使用LVM做熱備份方案也比較麻煩,因爲需要手動創建邏輯卷、遷移數據目錄、創建快照以及給數據庫加鎖等等,所以LVM並不是常用的熱備份方案。

XtraBackup方案

因爲LVM的麻煩,所以人們都希望使用專業的工具去做熱備份,這個工具就是XtraBackup。XtraBackup是由Percona開源的免費數據庫熱備份工具,它能對InnoDB數據庫和XtraDB存儲引擎的數據庫非阻塞地備份。因爲XtraBackup在備份過程中不會打斷正在執行的事務,而事務日誌中記錄了哪些是備份前寫入的數據哪些是備份後寫入的數據,所以無需加鎖。

另外,XtraBackup提供了對備份數據的壓縮功能,可以節約備份文件佔用的磁盤空間及網絡帶寬。但XtraBackup在備份使用MyISAM作爲存儲引擎的表時會加讀鎖,即表中的數據可讀但不可寫,不過這也不是問題,之前提到了可以使用聯機熱備份的方式來解決加讀鎖的問題。同樣,XtraBackup支持全量備份和增量備份,因爲XtraBackup的方便性,所以一般都是採用XtraBackup來做熱備份方案。

XtraBackup熱備份原理

因爲XtraBackup是主流的MySQL熱備份方案,所以這裏簡單介紹一下XtraBackup熱備份原理:

  • XtraBackup是一種物理備份工具,通過協議連接到MySQL服務端,然後讀取並複製底層的數據文件,完成物理備份。需要注意的是XtraBackup支持對InnoDB做全量備份和增量備份,但只能對MyISAM做全量備份
    數據庫熱備份神器 - XtraBackup

現在已經知道了XtraBackup是通過讀取並複製底層的數據文件,完成物理備份的。其中全量備份比較簡單,直接備份數據文件中的所有內容即可。而增量備份則需要區分新數據和舊數據,然後僅備份新數據,所以稍微複雜以些。

XtraBackup增量備份的原理如下:

增量備份只備份新增的數據,所以XtraBackup會去讀取數據文件中的內容來判斷哪些是舊數據哪些是新數據,然後只去備份新數據。在MySQL的數據文件裏,數據是存放在row這種結構中的,而row存放在page中,page則存在於extend中。

MySQL會爲每一個page都標記上一個LSN編號,通過對比該編號就可以得知哪些數據是新的,哪些數據是舊的。然後XtraBackup只需要從數據文件中,將這些新的page數據備份出來就行了。

示意圖:

數據庫熱備份神器 - XtraBackup

那麼XtraBackup是如何得知哪些LSN是新的呢?首先我們要知道LSN是一個全局遞增的編號,每次對page中的數據進行修改時都會產生新的LSN編號。假設現在有6個page,各自的LSN編號如下:
數據庫熱備份神器 - XtraBackup

上圖中,LSN編號爲3的表示被修改過3次,LSN編號爲5的表示被修改過5次,以此類推。假設此時對這些page進行一次全量備份,那麼這6個page都會被備份下來。經過一段時間後,其中有三個page被修改了,LSN編號發生了變化,如下所示:
數據庫熱備份神器 - XtraBackup

當進行增量備份時,XtraBackup就會將之前備份的pageLSN編號與數據文件中與之對應的pageLSN編號進行對比,若數據文件裏的LSN編號大於備份裏的LSN編號則代表數據文件中的page是新數據,那麼XtraBackup就會對其進行備份。若等於則代表數據沒有發生變化,不進行備份。因爲LSN編號是全局遞增的,所以不存在小於的情況。這就是XtraBackup增量備份的原理。


安裝XtraBackup

在瞭解了XtraBackup和其熱備份的實現原理後,接下來我們實踐一下如何使用該工具。首先需要安裝官方提供的yum倉庫:

[root@PXC-Node3 ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm

然後激活該yum倉庫:

[root@PXC-Node3 ~]# percona-release setup ps80

現在就可以直接通過yum命令本地安裝XtraBackup了:

[root@PXC-Node3 ~]# yum install -y percona-xtrabackup-24 

安裝完成後,輸出一下版本信息驗證xtrabackup命令是否可用:

[root@PXC-Node3 ~]# xtrabackup --version
xtrabackup: recognized server arguments: --server-id=3 --datadir=/var/lib/mysql --log_bin 
xtrabackup version 2.4.18 based on MySQL server 5.7.26 Linux (x86_64) (revision id: 29b4ca5)
[root@PXC-Node3 ~]# 

常用命令

XtraBackup命令種類:

序號 命令 描述
1 xbcrypt 用於加密或解密備份的數據
2 xbstream 用於壓縮或者解壓縮xbstream文件
3 xtrabackup 用於備份使用InnoDB、XtraDB作爲存儲引擎的數據表,該命令僅備份表數據文件,所以通常用在增量備份上
4 innobackupex 是上面三種命令的perl腳本封裝,可以使用該命令備份MyISAM數據表,並且只有使用該命令才能備份表數據文件、表定義文件、表索引文件,所以通常用在全量備份上

全量熱備份

使用innobackupex命令備份InnoDB數據表的流程圖:
數據庫熱備份神器 - XtraBackup

使用innobackupex命令進行全量熱備份示例:

[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --host=192.168.190.134 --user=admin --password=Abc_123456 --port=3306 /home/backup
  • --defaults-file:指定MySQL的配置文件所在路徑,因爲XtraBackup需要通過讀取配置文件才能知道數據目錄在哪
  • --host:指定MySQL服務的ip地址,因爲全量備份時需要備份表結構,所以得連接到MySQL加讀鎖
  • --user:指定使用哪個MySQL用戶進行備份
  • --password:MySQL用戶的密碼
  • --port:指定MySQL服務的端口號
  • /home/backup:備份文件存儲的目錄

備份的文件目錄如下:

[root@PXC-Node3 ~]# ls /home/backup/
2020-01-26_10-33-29
[root@PXC-Node3 ~]# ls /home/backup/2020-01-26_10-33-29/
backup-my.cnf   ibdata1  performance_schema  test  xtrabackup_binlog_info  xtrabackup_info
ib_buffer_pool  mysql    sys                 tpcc  xtrabackup_checkpoints  xtrabackup_logfile
[root@PXC-Node3 ~]#

以上這是一個最簡單的全量熱備份示例,可以看到備份出來的目錄和文件有很多,並且也沒有對這些備份文件進行壓縮。如果需要備份的數據量比較大的話,不壓縮備份文件就會很佔用存儲空間。但使用常規的壓縮命令,如tarzip等,則需要兩次I/O操作,因爲得先使用XtraBackup備份了數據之後,才能對產生的備份文件進行壓縮。因此備份的數據量較大時,對系統I/O和CPU的影響就比較明顯。

好在XtraBackup提供了流式壓縮的功能,通過流式壓縮可以將備份數據直接寫到壓縮文件中,而不用先備份再壓縮,所以只需要一次I/O操作。如下:
數據庫熱備份神器 - XtraBackup

想在備份時使用流式壓縮只需要指定--stream參數即可,如下示例:

[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --host=192.168.190.134 --user=admin --password=Abc_123456 --port=3306 --no-timestamp --stream=xbstream -> /home/backup/backup.xbstream
  • --no-timestamp:指定不生成時間戳目錄
  • --stream:指定使用的壓縮類型,目前只支持tarxbstream
  • /home/backup/backup.xbstream:指定生成的壓縮文件名稱

當備份一些涉及隱私的數據時,我們希望對備份文件進行加密,以防備份文件意外泄露時所帶來的影響。而XtraBackup也提供了加密備份的功能,與加密相關的參數如下:

序號 參數 描述
1 --encrypt 指定用於加密的算法:AES123、AES192、AES256
2 --encrypt-threads 指定執行加密的線程數
3 --encrypt-chunk-size 指定加密線程的緩存大小,默認64kb,大小不超過1M
4 --encrypt-key 指定用於加解密的密鑰字符串,長度至少24個字符
5 --encrypt-key-file 指定密鑰文件的路徑

加密備份示例:

[root@PXC-Node3 ~]# 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/encrypt-backup.xbstream

其他常用參數:

序號 參數 描述
1 --compress 針對InnoDB數據文件進行壓縮,可以與--stream參數同時使用
2 --compress-threads 指定執行壓縮的線程數
3 --compress-chunk-size 指定壓縮線程的緩存大小,默認64kb,大小不超過1M
4 --include 指定需要備份的數據表的正則表達式
5 --galera-info 指定備份PXC節點狀態文件

使用示例:

[root@PXC-Node3 ~]# 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' --compress --compress-threads=10 --include=test.student,test.t_orders --galera-info -> /home/backup/backup2.xbstream
  • --include:指明瞭僅備份test庫下的studentt_orders表,也可以寫正則表達式

全量冷還原

上面介紹了全量熱備份後,我們來看下如何將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/*
  • Tips:這裏由於是示例就直接使用rm刪除了,如果是實際的運行環境,建議先使用mv重命名需要刪除的目錄,最後還原完備份文件並驗證沒有問題後,再使用rm刪除,以避免刪庫跑路的悲劇發生

因爲是熱備份,所以事務日誌中可能會存在一些未完成的事務,這就需要回滾沒有提交的事務,以及同步已經提交的事務到數據文件。這裏以2020-01-26_10-33-29這個全量備份目錄作爲示例,執行如下命令:

[root@PXC-Node3 ~]# innobackupex --apply-log /home/backup/2020-01-26_10-33-29/

然後使用以下命令進行備份文件的還原:

[root@PXC-Node3 ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back /home/backup/2020-01-26_10-33-29/

接着給還原後的目錄文件賦予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

以上是對沒有使用流式壓縮,也沒有使用加密的備份文件做的演示。如果是備份文件使用了流式壓縮,則需要先使用xbstream命令對其進行解壓。如下示例:

# 創建解壓後文件的存儲目錄
[root@PXC-Node3 ~]# mkdir /home/backup/temp
[root@PXC-Node3 ~]# xbstream -x < /home/backup/backup2.xbstream -C /home/backup/temp/

如果備份文件使用了加密,則在解壓之後還需要對其進行解密:

[root@PXC-Node3 ~]# innobackupex --decompress --decrypt=AES256 --encrypt-key='1K!cNoq\&RUfQsY\&\&LAczTjco' /home/backup/temp
  • Tips:因爲&是特殊字符,所以需要使用\轉義一下。其中--decompress是與--compress對應的,用於解壓被壓縮的InnoDB數據文件,與解密無關

增量熱備份

增量熱備份必須以全量熱備份爲基礎進行備份,所以在瞭解了XtraBackup的全量熱備份和全量冷還原後,接下來就可以實踐XtraBackup的增量熱備份了。

注意事項:

  • 無論全量熱備份使用了流式壓縮還是內容加密,都必須解壓或解密成普通的備份目錄
  • 增量熱備份也同樣可以使用流式壓縮和內容加密

這裏以2020-01-26_10-33-29這個全量備份目錄作爲示例,增量熱備份命令如下:

[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/2020-01-26_10-33-29/ --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-02-21/
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/increment/2020-01-26_17-02-21/
3.3M    /home/backup/increment/2020-01-26_17-02-21/  # 增量熱備份的目錄大小
[root@PXC-Node3 ~]# du -sh /home/backup/2020-01-26_10-33-29/
836M    /home/backup/2020-01-26_10-33-29/  # 全量熱備份的目錄大小
[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-02-21/ --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-02-21/ --incremental --stream=xbstream --encrypt=AES256 --encrypt-threads=10 --encrypt-chunk-size 512 --encrypt-key='1K!cNoq&RUfQsY&&LAczTjco' ./ > /home/backup/increment
  • Tips:這裏的./表示將增量備份所有的內容都寫到流式壓縮文件裏,壓縮文件則存放在/home/backup/increment目錄下

增量冷還原

經過以上小節可以得知增量熱備份僅備份新數據,並且生成的備份目錄體積也要比全量熱備份生成的目錄體積要小很多。那麼XtraBackup要如何將增量備份的數據還原到數據庫呢?其實也很簡單,就是先將增量熱備份的數據與全量熱備份的數據合併,然後基於合併後的備份數據去還原即可。

增量熱備份可以有很多個備份點,因爲除第一次增量熱備份外,其餘的增量熱備份都是基於上一次增量熱備份進行的。所以在還原的時候也可以選擇任意一個備份點去還原,但事務日誌的處理步驟與全量冷還原不一樣。

在之前演示全量冷還原的時候,有一個處理事務日誌的步驟,同樣增量冷還原也有這個步驟,但是有些差異。上面提到增量熱備份是可以有多個備份點的,那麼在還原某一個備份點時就需要處理該備份點及其之前備份點的事務日誌,否則就會出現數據混亂的情況。如下圖,有三個備份點:
數據庫熱備份神器 - XtraBackup

例如,當還原“增量備份1”時,需要先處理其前一個備份點的事務日誌,即圖中的“全量熱備份”。接着再處理“增量備份1”這個備份點的事務日誌,然後合併“增量備份1”的數據到“全量熱備份”中。這樣才能保證多個備份點合併到全量備份點後的數據是一致的,最後還原“全量熱備份”中的數據即可。

再例如,要還原的是“增量備份2”,那麼就得先處理“全量熱備份”,然後處理“增量備份1”,接着處理“增量備份2”,按從前往後的順序依次將這三個備份點的事務日誌都給處理了後,才能合併備份點的數據到全量備份中,最後還原“全量熱備份”中的數據。其餘則以此類推......

接下來實操一下增量冷還原,這裏有三個與上圖對應的備份點目錄:

/home/backup/2020-01-26_10-33-29/  # 全量熱備份
/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/2020-01-26_10-33-29/
  • --redo-only:指定不回滾未提交的事務,因爲下個備份點的事務日誌裏可能會提交該備份點未提交的事務。如果回滾了就會導致下個備份點無法正常提交

然後處理“增量備份1”的事務日誌,並將"增量備份1"的數據合併到全量備份點上:

[root@PXC-Node3 ~]# innobackupex --apply-log --redo-only /home/backup/2020-01-26_10-33-29/ --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/2020-01-26_10-33-29/ --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/2020-01-26_10-33-29/  # 注意這裏指定的是全量備份點的目錄

接着給還原後的目錄文件賦予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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章