圖解MySQL邏輯備份的實現流程

1. 摘要

數據作為一家公司的重要資產,其重要程度不言而喻。資料庫為數據提供存取服務,擔任著重要的角色,如果因數據誤刪、伺服器故障、病毒入侵等原因導致數據丟失或服務不可用,會對公司造成重大損失,所以資料庫備份是數據系統中最為重要的一環。

MySQL備份按照類型分為邏輯備份、物理備份、快照備份,本文將通過圖文方式對常見的邏輯備份工具的一致性備份流程進行說明,來進一步了解邏輯備份的整個流程是怎麼實現的。

具體的資訊可以看: 圖解MySQL邏輯備份的實現流程

 

2. 概念

邏輯備份是資料庫對象級的備份,其將資料庫里的對象通過SQL查詢出來並轉儲到文件中,包含了用於創建轉儲對象(資料庫,表,觸發器、自定義函數、存儲過程等)的CREATE語句,和用於將數據載入到表中的INSERT語句。

 

一致性備份是指在某個時間點,導出的數據與導出的備份文件資訊匹配,如果導出了多張表的數據,這些不同表之間的數據都是同一個時間點的數據,MySQL可以通過全局鎖(FTWRL,鎖表備份)和事務(single-transaction,一致性快照)實現。

 

鎖表備份在Server層實現,備份期間該實例只能進行SELECT操作;事務的一致性快照備份在引擎層實現,支援MVCC引擎表(InnoDB)的備份,期間實例可以對任何錶進行DML操作,DDL操作需要根據具體情況分析,本文會對該情況(一致性快照備份)進行說明。

 

常見的邏輯備份工具:MySQL官方的mysqldump、mysqlpump、mysqlshell的dump方法和第三方開源的mydumper

 

3. 工具說明

3.1 mysqldump

  • 說明

mysqldump使用單執行緒對錶進行SELECT查詢並轉儲到文件來達到備份的目的,作為MySQL最「古老」的備份工具,被廣泛的使用在備份中。

 

  • 備份命令

mysqldump -udump_user -p -P3306 -h127.0.0.1 --master-data=2 --single-transaction --default-character-set=utf8 --all-databases --triggers --routines --events > all.sql
 
  • 備份流程

開啟 general_log 查看備份流程,大致的備份流程如下圖所示:

流程說明:

1. 連接資料庫,設置當前變數,刷臟頁並加一個全局讀鎖,此刻資料庫實例只能SELECT,不能執行其他任何類型的操作(會影響到業務),再設置事務隔離級別和開啟一致性快照,並獲取BINLOG和GITD資訊,此時所有的支援事務的表(INNODB)數據均來自同一時間點。最後再釋放全局讀鎖,此刻資料庫實例可以執行任何操作(正常情況下,加全局讀鎖和釋放鎖的時間很短)。

2. 獲取備份對象的元數據資訊並單執行緒導出表「SLEECT *」。導出表分3種情況:已經導出完成、還未導出和正在導出:

    • 對於已導出的表,可以做DDL操作(使用SAVEPOINT提前釋放導出表的metadata lock);

    • 對還未導出的表,INNODB表的DDL操作,能否執行成功取決於DDL的操作方式:no-rebuild方式的DDL執行成功,rebuild方式的DDL執行失敗(Table definition has changed),MyISAM引擎的表都能執行成功;

    • 對正在導出的表,DDL會出現MDL,此時對該表後續的查詢都會出現MDL,導致業務不可用(時間根據備份時長決定),直到該表導出完成。

3. 獲取除表外的其他對象:自定義函數、存儲過程、VIEW等。

4. 獲取當前的GTID資訊,所有對象的導出均轉儲到一個文件,完成備份。

 

3.2 mysqlpump

  • 說明

mysqlpump並行導出功能的架構為:隊列+執行緒,允許有多個隊列,每個隊列下有多個執行緒,一個隊列可以綁定1個或者多個資料庫。在mysqldump的基礎上額外支援了:並行備份、延遲創建索引、備份用戶、對象的通配符過濾、DEFINER忽略等特性。

 

mysqlpump的備份是基於表並行的,對於每張表的導出只能是單個執行緒的,如果一張表非常大,大部分的時間都是消耗在這個表的備份上,並行備份的效果可能就不明顯。

 

  • 備份命令

    mysqlpump -udump_user -p -P3306 -h127.0.0.1 --set-gtid-purged=on --default-parallelism=2  --single-transaction --default-character-set=utf8 --exclude-databases=mysql,sys,information_schema,performance_schema > all.sql

     

  • 備份流程

開啟 general_log 查看備份流程,大致的備份流程如下圖所示:

圖片

流程說明:

1. 多執行緒連接資料庫,設置當前變數,刷臟頁並加一個全局讀鎖,此刻資料庫實例只能SELECT,不能執行任何類型的操作(會影響業務),再設置事務隔離級別和開啟一致性快照讀並獲取GITD 資訊,此時所有的支援事務的表(INNODB)數據均來自同一時間點。最後再釋放全局讀鎖,此刻資料庫實例可以執行任何操作(正常情況下,加全局讀鎖和釋放鎖的時間很短)。

2. 獲取除表外的其他對象:自定義函數、存儲過程、VIEW等。

3. 獲取備份對象的元數據資訊並多執行緒導出表「SLEECT col1,col2,…」。導出表分3種情況:已經導出完成、還未導出和正在導出:

    • 對於已導出的表,不能做DDL操作(不支援SAVEPOINT);

    • 對還未導出的表,INNODB表的DDL操作,能否執行成功取決於DDL的操作方式:no-rebuild方式的DDL執行成功,rebuild方式的DDL執行失敗(Table definition has changed),MyISAM引擎的表都能執行成功,但如果表結構先於DDL導出,再導出數據,則在還原的時候會報異常(表結構和導出的數據不一致);

    • 對正在導出的表,DDL會出現MDL,此時對該表後續的查詢都會出現MDL,導致業務不可用(時間根據備份時長決定),直到該表導出完成。

4. 所有對象的備份均轉儲到一個文件,完成備份。備份文件中存儲的表結構中只有主鍵,二級索引單獨一行存儲,目的是在恢復完數據後再添加二級索引,提高恢復效率(延遲創建索引)。

 

3.3 mydumper

  • 說明

mydumper利用INNODB的MVCC版本控制的功能,實現多執行緒並發獲取一致性數據。特別是表以chunk的方式批量導出,即支援一張表多個執行緒以chunk的方式批量導出(基於行的多執行緒),備份的對象支援正則匹配。

 

  • 備份命令

mydumper -u dump_user -p -h 127.0.0.1 -P 3306 --use-savepoints --trx-consistency-only -r 100000 -t 2 -G -R -E -B sbtest -o /data/backup/

  –trx-consistency-only:如果不加,則FTWRL的鎖在備份完成之後釋放。加了會在獲取到一致性快照讀之後釋放(UNLOCK TABLES)。

  –rows:-r,分片導出的行數。

  –use-savepoints 和 –rows互斥。

 

  • 備份流程

開啟 general_log 查看備份流程,大致的備份流程如下圖所示:

圖片

流程說明:

1. 連接資料庫,設置當前變數,刷臟頁並加一個全局讀鎖,此刻資料庫實例只能SELECT,不能執行任何類型的操作(會影響業務),再獲取BINLOG和GITD 資訊並設置事務隔離級別和開啟一致性快照,此時所有的支援事務的表(INNODB)數據均來自同一時間點。最後再釋放全局讀鎖,此刻資料庫實例可以執行任何操作(正常情況,加全局讀鎖和釋放鎖的時間很短)。

2. 獲取備份對象的元數據資訊並多執行緒導出表「SLEECT *」。導出表分3種情況:已經導出完成、還未導出和正在導出:

    • 對於已導出的表,可以做DDL操作(使用SAVEPOINT提前釋放導出表的metadata lock,如果使用分片導出,SAVEPOINT將不可用);

    • 對還未導出的表,INNODB表的DDL操作,能否執行成功取決於DDL的操作方式:no-rebuild方式的DDL執行成功,rebuild方式的DDL執行失敗(Table definition has changed),MyISAM引擎的表都能執行成功;

    • 對正在導出的表,DDL會出現MDL,此時對該表後續的查詢都會出現MDL,導致業務不可用(時間根據備份時長決定),直到該表導出完成。

3. 所有表都導出完成後,再獲取除表外的其他對象:自定義函數、存儲過程、VIEW等

4. 所有對象的導出均轉儲到多個文件(將表數據分塊導出成多個數據文件),完成備份。

 

3.4 mysqlshell

  • 說明

MySQL Shell 是Oracle官方提供的一個互動式工具,用於開發和管理MySQL的伺服器。其中的util.dumpInstance、util.dumpSchemas、util.loadDump 等是對MySQL進行備份管理,使用zstd實時壓縮演算法,支援多執行緒備份,以chunk的方式批量導出,支援一張表多個執行緒以chunk的方式批量導出。

 

  • 備份命令

util.dumpSchemas(['sbtest'],'/data/backup',{"threads":1,"consistent":true})

 

  • 備份流程

圖片

流程說明:

1. 連接資料庫,設置當前變數,刷臟頁並加一個全局讀鎖,此刻資料庫實例只能SELECT,不能執行任何類型的操作(會影響業務),再獲取BINLOG、GITD和備份對象的元數據資訊,接著設置事務隔離級別和啟動一致性快照,此時所有的支援事務的表(INNODB)數據均來自同一時間點。最後再釋放全局讀鎖,此刻資料庫實例可以執行任何操作(正常情況,加全局讀鎖和釋放鎖的時間很短)。

2. 獲取備份對象:自定義函數、存儲過程、VIEW等。

3. 多執行緒導出表「SLEECT col1,col2,…」。導出表分3種情況:已經導出完成、還未導出和正在導出:

  • 對於已導出的表,不能做DDL操作(不支援SAVEPOINT);

  • 對還未導出的表,需要區分有沒有PK或UK:

    • 沒有PK和UK,還要根據DDL的操作方式:no-rebuild方式的DDL執行成功,rebuild方式的DDL執行失敗(Table definition has changed),MyISAM引擎的表都能執行成功;

    • 有PK或UK,和正在導出的表情況一樣,原因是在獲取分片資訊時需要查詢表的最大最小值。

  • 對正在導出的表,DDL會出現MDL,此時對該表後續的查詢都會出現MDL,導致業務不可用(時間根據備份時長決定),直到該表導出完成。

4. 所有對象的導出均轉存到多個文件(將表數據分塊導出成多個數據文件),完成備份。

 

3.5 小結

從上面各邏輯備份的流程中看到,在一致性備份下,所有表的DML操作不影響(除FTWRL短暫的時刻外),而DDL操作都存在一定的風險。所以在邏輯備份期間,要盡量避免DDL操作

 

各邏輯備份工具的參數可以看官方文檔,對比各工具之後,如表所示:

圖片

推薦使用的邏輯備份,需要具備的條件:支援一致性備份、行級別的分片多執行緒導出、導出到多個文件(恢復快),延遲創建索引和savepoint能力。從上面表中看到,mydumpermysqlshell中的dump方法能滿足較多的條件。

 

 

4. 總結

希望通過閱讀本文,能讓大家更清晰的了解邏輯備份的整個實現流程,在選擇合適的邏輯備份時有幫助。