天天看點

圖解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 檢視備份流程,大緻的備份流程如下圖所示:

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

流程說明:

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 檢視備份流程,大緻的備份流程如下圖所示:

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

流程說明:

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 檢視備份流程,大緻的備份流程如下圖所示:

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

流程說明:

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})      
  • 備份流程
圖解MySQL邏輯備份的實作流程

流程說明:

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操作。

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

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

推薦使用的邏輯備份,需要具備的條件:支援一緻性備份、行級别的分片多線程導出、導出到多個檔案(恢複快),延遲建立索引和savepoint能力。從上面表中看到,mydumper和mysqlshell中的dump方法能滿足較多的條件。

4. 總結

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

~~~~~~~~~~~~~~~

萬物之中,希望至美

~~~~~~~~~~~~~~~

繼續閱讀