MySQL經常使用備份策略詳解 —— mysqldump、mysqlpump 和 Xtrabackup

1、備份簡介

2.1 備份分類

按照不一樣的思考維度,一般將數據庫的備份分爲如下幾類:html

物理備份 與 邏輯備份mysql

  • 物理備份:備份的是完整的數據庫目錄和數據文件。採用該模式會進行大量的 IO 操做,但不含任何邏輯轉換,所以備份和恢復速度一般都比較快。
  • 邏輯備份:經過數據庫結構和內容信息來進行備份。由於要執行邏輯轉換,所以其速度較慢,而且在以文本格式保存時,其輸出文件的大小大於物理備份。邏輯備份的還原的粒度能夠從服務器級別(全部數據庫)精確到具體表,但備份不會包括日誌文件、配置文件等與數據庫無關的內容。

全量備份 與 增量備份git

  • 全量備份:備份服務器在給定時間點上的全部數據。
  • 增量備份:備份在給定時間跨度內(從一個時間點到另外一個時間點)對數據所作的更改。

在線備份 與 離線備份github

  • 在線備份:數據庫服務在運行狀態下進行備份。此時其餘客戶端依舊能夠鏈接到數據庫,但爲了保證數據的一致性,在備份期間可能會對數據進行加鎖,此時客戶端的訪問依然會受限。
  • 離線備份:在數據庫服務停機狀態下進行備份。此備份過程簡單,但因爲沒法提供對外服務,一般會對業務形成比較大的影響。

2.2 備份工具

MySQL 支持的備份工具備不少種,這裏列出經常使用的三種:算法

  • mysqldump:這是 MySQL 自帶的備份工具,其採用的備份方式是邏輯備份,支持全庫備份、單庫備份、單表備份。因爲其採用的是邏輯備份,因此生成的備份文件比物理備份的大,且所需恢復時間也比較長。
  • mysqlpump:這是 MySQL 5.7 以後新增的備份工具,在 mysqldump 的基礎上進行了功能的擴展,支持多線程備份,支持對備份文件進行壓縮,可以提升備份的速度和下降備份文件所需的儲存空間。
  • Xtrabackup:這是 Percona 公司開發的實時熱備工具,可以在不停機的狀況下進行快速可靠的熱備份,而且備份期間不會間斷數據庫事務的處理。它支持數據的全備和增備,而且因爲其採用的是物理備份的方式,因此恢復速度比較快。

2、mysqldump

2.1 經常使用參數

mysqldump 的基本語法以下:sql

# 備份數據庫或數據庫中的指定表
mysqldump [options] db_name [tbl_name ...]
# 備份多個指定的數據庫
mysqldump [options] --databases db_name ...
# 備份當前數據庫實例中的全部表
mysqldump [options] --all-databases
複製代碼

options 表明可選操做,經常使用的可選參數以下:shell

  • --host=host_name, -h host_name數據庫

    指定服務器地址。緩存

  • --user=user_name, -u user_namebash

    指定用戶名。

  • --password[=password], -p[password]

    指定密碼。一般無需在命令行中明文指定,按照提示輸入便可。

  • --default-character-set=charset_name

    導出文本使用的字符集,默認爲 utf8。

  • --events, -E

    備份包含數據庫中的事件。

  • --ignore-table=db_name.tbl_name

    不須要進行備份的表,必須使用數據庫和表名來共同指定。也能夠做用於視圖。

  • --routines, -R

    備份包含數據庫中的存儲過程和自定義函數。

  • --triggers

    備份包含數據庫中的觸發器。

  • --where='where_condition', -w 'where_condition'

    在對單表進行導出時候,能夠指定過濾條件,例如指定用戶名 --where="user='jimf'" 或用戶範圍 -w"userid>1"

  • --lock-all-tables, -x

    鎖定全部數據庫中的全部表,從而保證備份數據的一致性。此選項自動關閉 --single-transaction--lock-tables

  • --lock-tables, -l

    鎖定當前數據庫中全部表,可以保證當前數據庫中表的一致性,但不能保證全局的一致性。

  • --single-transaction

    此選項會將事務隔離模式設置爲 REPEATABLE READ 並開啓一個事務,從而保證備份數據的一致性。主要用於事務表,如 InnoDB 表。 可是此時仍然不能在備份表上執行 ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 等操做,由於 REPEATABLE READ 並不能隔離這些操做。

    另外須要注意的是 --single-transaction 選項與 --lock-tables 選項是互斥的,由於 LOCK TABLES 會致使任何正在掛起的事務被隱式提交。轉儲大表時,能夠將 --single-transaction 選項與 --quick 選項組合使用 。

  • --quick, -q

    主要用於備份大表。它強制 mysqldump 一次只從服務器檢索一行數據,避免一次檢索全部行而致使緩存溢出。

  • --flush-logs, -F

    在開始備份前刷新 MySQL 的日誌文件。此選項須要 RELOAD 權限。若是此選項與 --all-databases 配合使用,則會在每一個數據庫開始備份前都刷新一第二天志。若是配合 --lock-all-tables--master-data--single-transaction 使用,則只會在鎖定全部表或者開啓事務時刷新一次。

  • --master-data[=value]

    能夠經過配置此參數來控制生成的備份文件是否包含 CHANGE MASTER 語句,該語句中包含了當前時間點二進制日誌的信息。該選項有兩個可選值:1 和 2 ,設置爲 1 時 CHANGE MASTER 語句正常生成,設置爲 2 時以註釋的方式生成。--master-data 選項還會自動關閉 --lock-tables 選項,並且若是你沒有指定 --single-transaction 選項,那麼它還會啓用 --lock-all-tables 選項,在這種狀況下,會在備份開始時短暫內獲取全局讀鎖。

2.2 全量備份

mysqldump 的全量備份與恢復的操做比較簡單,示例以下:

# 備份僱員庫
mysqldump  -uroot -p --databases employees > employees_bak.sql
 # 恢復僱員庫
mysql -uroot -p  < employees_bak.sql
複製代碼

單表備份:

# 備份僱員庫中的職位表
mysqldump  -uroot -p --single-transaction employees titles > titles_bak.sql
 # 恢復僱員庫中的職位表
mysql> use employees;
mysql> source /root/mysqldata/titles_bak.sql;
複製代碼

2.3 增量備份

mysqldump 自己並不能直接進行增量備份,須要經過分析二進制日誌的方式來完成。具體示例以下:

1. 基礎全備

1.先執行一次全備做爲基礎,這裏以單表備份爲例,須要用到上文提到的 --master-data 參數,語句以下:

mysqldump -uroot -p --master-data=2 --flush-logs employees titles > titles_bak.sql
複製代碼

使用 more 命令查看備份文件,此時能夠在文件開頭看到 CHANGE MASTER 語句,語句中包含了二進制日誌的名稱和偏移量信息,具體以下:

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=155;
複製代碼

2. 增量恢復

對錶內容進行任意修改,而後經過分析二進制日誌文件來生成增量備份的腳本文件,示例以下:

mysqlbinlog --start-position=155 \
--database=employees  ${MYSQL_HOME}/data/mysql-bin.000004 > titles_inr_bak_01.sql
複製代碼

須要注意的是,在實際生產環境中,可能在全量備份後與增量備份前的時間間隔裏生成了多份二進制文件,此時須要對每個二進制文件都執行相同的命令:

mysqlbinlog --database=employees  ${MYSQL_HOME}/data/mysql-bin.000005 > titles_inr_bak_02.sql
mysqlbinlog --database=employees  ${MYSQL_HOME}/data/mysql-bin.000006 > titles_inr_bak_03.sql
.....
複製代碼

以後將全備腳本 ( titles_bak.sql ),以及全部的增備腳本 ( inr_01.sql,inr_02.sql .... ) 經過 source 命令導入便可,這樣就完成了全量 + 增量的恢復。

3、mysqlpump

3.1 功能優點

mysqlpump 在 mysqldump 的基礎上進行了擴展加強,其主要的優勢以下:

  • 可以並行處理數據庫及其中的對象,從而能夠加快備份進程;

  • 可以更好地控制數據庫及數據庫對象(表,存儲過程,用戶賬戶等);

  • 可以直接對備份文件進行壓縮;

  • 備份時可以顯示進度指標(估計值);

  • 備份用戶時生成的是 CREATE USER 與 GRANT 語句,而不是像 mysqldump 同樣備份成數據,能夠方便用戶按需恢復。

3.2 經常使用參數

mysqlpump 的使用和 mysqldump 基本一致,這裏再也不進行贅述。如下主要介紹部分新增的可選項,具體以下:

  • --default-parallelism=N

    每一個並行處理隊列的默認線程數。默認值爲 2。

  • --parallel-schemas=[N:]db_list

    用於並行備份多個數據庫:db_list 是一個或多個以逗號分隔的數據庫名稱列表;N 爲使用的線程數,若是沒有設置,則使用 --default-parallelism 參數的值。

  • --users

    將用戶信息備份爲 CREATE USER 語句和 GRANT 語句 。若是想要只備份用戶信息,則可使用下面的命令:

    mysqlpump --exclude-databases=% --users
    複製代碼
  • --compress-output=algorithm

    默認狀況下,mysqlpump 不對備份文件進行壓縮。可使用該選項指定壓縮格式,當前支持 LZ4 和 ZLIB 兩種格式。須要注意的是壓縮後的文件能夠佔用更少的存儲空間,可是卻不能直接用於備份恢復,須要先進行解壓,具體以下:

    # 採用lz4算法進行壓縮
    mysqlpump --compress-output=LZ4 > dump.lz4
    # 恢復前須要先進行解壓
    lz4_decompress input_file output_file
     # 採用ZLIB算法進行壓縮
    mysqlpump --compress-output=ZLIB > dump.zlib
    zlib_decompress input_file output_file
    複製代碼

    MySQL 發行版自帶了上面兩個壓縮工具,不須要進行額外安裝。以上就是 mysqlpump 新增的部分經常使用參數,完整參數能夠參考官方文檔:mysqlpump — A Database Backup Program

4、Xtrabackup

4.1 在線安裝

Xtrabackup 能夠直接使用 yum 命令進行安裝,這裏個人 MySQL 爲 8.0 ,對應安裝的 Xtrabackup 也爲 8.0,命令以下:

# 安裝Percona yum 源
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
 # 安裝
yum install percona-xtrabackup-80
複製代碼

4.2 全量備份

全量備份的具體步驟以下:

1. 建立備份

Xtrabackup 全量備份的基本語句以下,可使用 target-dir 指明備份文件的存儲位置,parallel 則是指明操做的並行度:

xtrabackup --backup  --user=root --password --parallel=3  --target-dir=/data/backups/
複製代碼

以上進行的是整個數據庫實例的備份,若是須要備份指定數據庫,則可使用 --databases 進行指定。

另一個容易出現的異常是:Xtrabackup 在進行備份時,默認會去 /var/lib/mysql/mysql.sock 文件裏獲取數據庫的 socket 信息,若是你修改了數據庫的 socket 配置,則須要使用 --socket 參數進行從新指定,不然會拋出找不到鏈接的異常。備份完整後須要當即執行的另一個操做是 prepare (準備備份)。

2. 準備備份

因爲備份是將全部物理庫表等文件複製到備份目錄,而整個過程須要持續一段時間,此時備份的數據中就可能會包含還沒有提交的事務或已經提交但還沒有同步至數據文件中的事務,最終致使備份結果處於不一致狀態。此時須要進行 prepare 操做來回滾未提交的事務及同步已經提交的事務至數據文件,從而使得總體達到一致性狀態。命令以下:

xtrabackup --prepare --target-dir=/data/backups/
複製代碼

須要特別注意的在該階段不要隨意中斷 xtrabackup 進程,由於這可能會致使數據文件損壞,備份將沒法使用。

3. 恢復備份

因爲 xtrabackup 執行的是物理備份,因此想要進行恢復,必須先要中止 MySQL 服務。同時這裏咱們能夠刪除 MySQL 的數據目錄來模擬數據丟失的狀況,以後使用如下命令將備份文件拷貝到 MySQL 的數據目錄下:

# 模擬數據異常丟失
rm -rf /usr/app/mysql-8.0.17/data/*
 # 將備份文件拷貝到 data 目錄下
xtrabackup --copy-back --target-dir=/data/backups/
複製代碼

copy-back 命令只須要指定備份文件的位置,不須要指定 MySQL 數據目錄的位置,由於 Xtrabackup 會自動從 /etc/my.cnf 上獲取 MySQL 的相關信息,包括數據目錄的位置。若是不須要保留備份文件,能夠直接使用 --move-back 命令,表明直接將備份文件移動到數據目錄下。此時數據目錄的全部者一般爲執行命令的用戶,須要更改成 mysql 用戶,命令以下:

chown -R mysql:mysql /usr/app/mysql-8.0.17/data
複製代碼

再次啓動便可完成備份恢復。

4.3 增量備份

使用 Xtrabackup 進行增量備份時,每一次增量備份都須要以上一次的備份爲基礎,以後再將增量備份運用到第一次全備之上,從而完成備份。具體操做以下:

1. 建立備份

這裏首先建立一個全備做爲基礎:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/base/
複製代碼

以後修改庫中任意數據,而後進行第一次增量備份,此時須要使用 incremental-basedir 指定基礎目錄爲全備目錄:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/inc1 \
--incremental-basedir=/data/backups/base
複製代碼

再修改庫中任意數據,而後進行第二次增量備份,此時須要使用 incremental-basedir 指定基礎目錄爲上一次增備目錄:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/inc2 \
--incremental-basedir=/data/backups/inc1
複製代碼

2. 準備備份

準備基礎備份:

xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base
複製代碼

將第一次備份做用於全備數據:

xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base \
--incremental-dir=/data/backups/inc1
複製代碼

將第二次備份做用於全備數據:

xtrabackup --prepare --target-dir=/data/backups/base \
--incremental-dir=/data/backups/inc2
複製代碼

在準備備份時候,除了最後一次增備外,其他的準備命令都須要加上 --apply-log-only 選項來阻止事務的回滾,由於備份時未提交的事務可能正在進行,並可能在下一次增量備份中提交,若是不進行阻止,那麼增量備份將沒有任何意義。

3. 恢復備份

恢復備份和全量備份時相同,只須要最終準備好的全備數據複製到 MySQL 的數據目錄下便可:

xtrabackup --copy-back --target-dir=/data/backups/base
# 必須修改文件權限,不然沒法啓動
chown -R mysql:mysql /usr/app/mysql-8.0.17/data
複製代碼

此時增量備份就已經完成。須要說明的是:按照上面的狀況,若是第二次備份以後發生了宕機,那麼第二次備份後到宕機前的數據依然無法經過 Xtrabackup 進行恢復,此時就只能採用上面介紹的分析二進制日誌的恢復方法。由此能夠看出,不管是採用何種備份方式,二進制日誌都是很是重要的,所以最好對其進行實時備份。

5、二進制日誌的備份

想要備份二進制日誌文件,能夠經過定時執行 cp 或 scp 等命令來實現,也能夠經過 mysqlbinlog 自帶的功能來實現遠程備份,將遠程服務器上的二進制日誌文件複製到本機,命令以下:

mysqlbinlog --read-from-remote-server --raw --stop-never \
--host=主機名 --port=3306 \
--user=用戶名 --password=密碼  初始複製時的日誌文件名
複製代碼

須要注意的是這裏的用戶必須具備 replication slave 權限,由於上述命令本質上是模擬主從複製架構下,從節點經過 IO 線程不斷去獲取主節點的二進制日誌,從而達到備份的目的。

參考資料

更多文章,歡迎訪問 [全棧工程師手冊] ,GitHub 地址:github.com/heibaiying/…

相關文章
相關標籤/搜索