圖解MySQL邏輯備份的實(shí)現(xiàn)流程
1. 摘要
數(shù)據(jù)作為一家公司的重要資產(chǎn),其重要程度不言而喻。數(shù)據(jù)庫為數(shù)據(jù)提供存取服務(wù),擔(dān)任著重要的角色,如果因 數(shù)據(jù) 誤刪、服務(wù)器故障、病毒入侵等原因?qū)е聰?shù)據(jù)丟失或服務(wù)不可用,會(huì)對公司造成重大損失,所以數(shù)據(jù)庫備份是數(shù)據(jù)系統(tǒng)中最為重要的一環(huán)。
MySQL備份按照類型分為 邏輯備份、物理備份、快照備份 ,本文將 通過 圖文方式 對常見的邏輯備份 工具 的 一致性備份 流程進(jìn)行說明,來進(jìn)一步了解邏輯備份的整個(gè)流程是怎么實(shí)現(xiàn)的。
2. 概念
邏輯備份是數(shù)據(jù)庫對象級的備份,其將數(shù)據(jù)庫里的對象通過SQL查詢出來并轉(zhuǎn)儲(chǔ)到文件中, 包含了用于創(chuàng)建轉(zhuǎn)儲(chǔ)對象(數(shù)據(jù)庫,表,觸發(fā)器、自定義函數(shù)、存儲(chǔ)過程等)的CREATE語句,和用于將數(shù)據(jù)加載到表中的INSERT語句。
一致性備份 是指在某個(gè)時(shí)間點(diǎn),導(dǎo)出的數(shù)據(jù)與導(dǎo)出的備份文件信息匹配,如果導(dǎo)出了多張表的數(shù)據(jù),這些不同表之間的數(shù)據(jù)都是同一個(gè)時(shí)間點(diǎn)的數(shù)據(jù),MySQL可以通過全局鎖(FTWRL,鎖表備份)和事務(wù)( single -trans ac tion, 一致性快 照 )實(shí)現(xiàn)。
鎖表備份在Server層實(shí)現(xiàn),備份期間該實(shí)例只能進(jìn)行SELECT操作;事務(wù)的 一致性快照備份在引擎層實(shí)現(xiàn),支持MVCC引擎表 (InnoDB) 的備份,期間實(shí)例可以對任何表進(jìn)行 DML 操作,DDL操作需要根據(jù)具體情況分析,本文會(huì)對該情況(一致性快照備份)進(jìn)行說明。
常見的邏輯備份工具 : MySQL官方的 mysqldump、 mysqlpump、 mysqlshell 的dump方法和第三方開源的 mydumper 。
3. 工具說明
3.1 mysqldump
說明
mysqldump 使用 單線程 對表進(jìn)行SELECT查詢并轉(zhuǎn)儲(chǔ)到文件來達(dá)到備份的目的,作為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. 連接數(shù)據(jù)庫,設(shè)置當(dāng)前變量,刷臟頁并加一個(gè)全局讀鎖,此刻數(shù)據(jù)庫實(shí)例只能SELECT,不能執(zhí)行其他任何類型的操作(會(huì)影響到業(yè)務(wù)),再設(shè)置事務(wù)隔離級別和開啟一致性快照,并獲取BINLOG和GITD信息,此時(shí)所有的支持事務(wù)的表(INNODB)數(shù)據(jù)均來自同一時(shí)間點(diǎn)。最后再釋放全局讀鎖,此刻數(shù)據(jù)庫實(shí)例可以執(zhí)行任何操作(正常情況下,加全局讀鎖和釋放鎖的時(shí)間很短)。
2. 獲取備份對象的元數(shù)據(jù)信息并 單線程 導(dǎo)出表「 SLEECT * 」。導(dǎo)出表分3種情況:已經(jīng)導(dǎo)出完成、還未導(dǎo)出和正在導(dǎo)出:
- 對于 已導(dǎo)出的 表,可以做DDL操作( 使用 SAVEPOINT提前釋放 導(dǎo)出表的 metadata lock );
- 對還未導(dǎo)出的表, INNODB 表的DDL操作,能否執(zhí)行成功取決于DDL的操作方式: no-rebuild 方式的DDL執(zhí)行成功, rebuild 方式的DDL執(zhí)行失敗( Table definition has changed),MyISAM引擎的表都能執(zhí)行成功;
- 對正在導(dǎo)出的表,DDL會(huì)出現(xiàn)MDL,此時(shí)對該表后續(xù)的查詢都會(huì)出現(xiàn)MDL,導(dǎo)致業(yè)務(wù)不可用(時(shí)間根據(jù)備份時(shí)長決定),直到該表導(dǎo)出完成。
3. 獲取除表外的其他對象:自定義函數(shù)、存儲(chǔ)過程、VIEW等。
4. 獲取當(dāng)前的GTID信息,所有對象的導(dǎo)出均轉(zhuǎn)儲(chǔ)到 一個(gè)文件 ,完成備份。
3.2 mysqlpump
- 說明
mysqlpump 并行導(dǎo)出 功能的架構(gòu)為:隊(duì)列+線程,允許有多個(gè)隊(duì)列,每個(gè)隊(duì)列下有多個(gè)線程,一個(gè)隊(duì)列可以綁定1個(gè)或者多個(gè)數(shù)據(jù)庫。 在mysqldump的基礎(chǔ)上額外支持了:并行備份、 延遲創(chuàng)建索引、 備份用戶、對象的通配符過濾、 DEFINER忽略等特性。
mysqlpump的備份是基于表并行的,對于每張表的導(dǎo)出只能是單個(gè)線程的,如果一張表非常大,大部分的時(shí)間都是消耗在這個(gè)表的備份上,并行備份的效果可能就不明顯。
- 備份命令
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. 多線程連接數(shù)據(jù)庫,設(shè)置當(dāng)前變量,刷臟頁并加一個(gè)全局讀鎖,此刻數(shù)據(jù)庫實(shí)例只能SELECT,不能執(zhí)行任何類型的操作(會(huì)影響業(yè)務(wù)),再設(shè)置事務(wù)隔離級別和開啟一致性快照讀并獲取GITD 信息,此時(shí)所有的支持事務(wù)的表(INNODB)數(shù)據(jù)均來自同一時(shí)間點(diǎn)。最后再釋放全局讀鎖,此刻數(shù)據(jù)庫實(shí)例可以執(zhí)行任何操作(正常情況下,加全局讀鎖和釋放鎖的時(shí)間很短)。
2.獲取除表外的其他對象:自定義函數(shù)、存儲(chǔ)過程、VIEW等。
3. 獲取備份對象的元數(shù)據(jù)信息并 多線程 導(dǎo)出表 「 SLEECT col1,col2,... 」。導(dǎo)出表分3種情況:已經(jīng)導(dǎo)出完成、還未導(dǎo)出和正在導(dǎo)出:
- 對于 已導(dǎo)出的 表, 不能 做DDL操作(不支持SAVEPOINT);
- 對還未導(dǎo)出的表, INNODB 表的DDL操作,能否執(zhí)行成功取決于DDL的操作方式: no-rebuild 方式的DDL執(zhí)行成功, rebuild 方式的DDL執(zhí)行失?。?nbsp;Table definition has changed),MyISAM引擎的表都能執(zhí)行成功, 但如果表結(jié)構(gòu)先于DDL導(dǎo)出,再導(dǎo)出數(shù)據(jù),則在還原的時(shí)候會(huì)報(bào)異常(表結(jié)構(gòu)和導(dǎo)出的數(shù)據(jù)不一致);
- 對正在導(dǎo)出的表,DDL會(huì)出現(xiàn)MDL,此時(shí)對該表后續(xù)的查詢都會(huì)出現(xiàn)MDL,導(dǎo)致業(yè)務(wù)不可用(時(shí)間根據(jù)備份時(shí)長決定),直到該表導(dǎo)出完成。
4. 所有對象的備份均轉(zhuǎn)儲(chǔ)到 一個(gè)文件 ,完成備份。 備 份文件中存儲(chǔ)的表結(jié)構(gòu)中只有主鍵,二級索引單獨(dú)一行存儲(chǔ),目的是在恢復(fù)完數(shù)據(jù)后再添加二級索引,提高恢復(fù)效率(延遲創(chuàng)建索引) 。
3.3 mydumper
- 說明
mydumper利用INNODB的MVCC版本控制的功能,實(shí)現(xiàn) 多線程 并發(fā)獲取一致性數(shù)據(jù)。特別是表以chunk的方式批量導(dǎo)出,即支持一張表多個(gè)線程以chunk的方式批量導(dǎo)出(基于行的多線程), 備份的對象支持正則匹配 。
- 備份命令
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的鎖在備份完成之后釋放。加了會(huì)在獲取到一致性快照讀之后釋放(UNLOCK TABLES)。
--rows:-r,分片導(dǎo)出的行數(shù)。
--use-savepoints 和 --rows互斥。
- 備份流程
開啟 general_log 查看備份流程,大致的備份流程如下圖所示:
流程說明:
1. 連接數(shù)據(jù)庫,設(shè)置當(dāng)前變量,刷臟頁并加一個(gè)全局讀鎖,此刻數(shù)據(jù)庫實(shí)例只能SELECT,不能執(zhí)行任何類型的操作(會(huì)影響業(yè)務(wù)),再獲取BINLOG和GITD 信息并設(shè)置事務(wù)隔離級別和開啟一致性快照,此時(shí)所有的支持事務(wù)的表(INNODB)數(shù)據(jù)均來自同一時(shí)間點(diǎn)。最后再釋放全局讀鎖,此刻數(shù)據(jù)庫實(shí)例可以執(zhí)行任何操作(正常情況,加全局讀鎖和釋放鎖的時(shí)間很短)。
2. 獲取備份對象的元數(shù)據(jù)信息并 多線程 導(dǎo)出表「 SLEECT * 」。導(dǎo)出表分3種情況:已經(jīng)導(dǎo)出完成、還未導(dǎo)出和正在導(dǎo)出:
- 對于 已導(dǎo)出的 表,可以做DDL操作( 使用 SAVEPOINT提前釋放 導(dǎo)出表的 metadata lock ,如果使用分片導(dǎo)出, SAVEPOINT 將不可用 );
- 對還未導(dǎo)出的表, INNODB 表的DDL操作,能否執(zhí)行成功取決于DDL的操作方式: no-rebuild 方式的DDL執(zhí)行成功, rebuild 方式的DDL執(zhí)行失敗( Table definition has changed),MyISAM引擎的表都能執(zhí)行成功;
- 對正在導(dǎo)出的表,DDL會(huì)出現(xiàn)MDL,此時(shí)對該表后續(xù)的查詢都會(huì)出現(xiàn)MDL,導(dǎo)致業(yè)務(wù)不可用(時(shí)間根據(jù)備份時(shí)長決定),直到該表導(dǎo)出完成。
3. 所有表都導(dǎo)出完成后,再獲取除表外的其他對象:自定義函數(shù)、存儲(chǔ)過程、VIEW等
4.所有對象的導(dǎo)出均轉(zhuǎn)儲(chǔ)到 多個(gè)文件 ( 將表數(shù)據(jù)分塊導(dǎo)出 成多個(gè)數(shù)據(jù)文件 ) ,完成備份。
3.4 mysqlshell
- 說明
MySQL Shell 是Oracle官方提供的一個(gè)交互式工具,用于開發(fā)和管理MySQL的服務(wù)器。其中的util.dumpInstance、util.dumpSchemas、util.loadDump 等是對MySQL進(jìn)行備份管理,使用zstd實(shí)時(shí)壓縮算法,支持 多線程 備份,以chunk的方式批量導(dǎo)出,支持一張表多個(gè)線程以chunk的方式批量導(dǎo)出。
- 備份命令
util.dumpSchemas(['sbtest'],'/data/backup',{"threads":1,"consistent":true})
- 備份流程
流程說明:
1. 連接數(shù)據(jù)庫,設(shè)置當(dāng)前變量,刷臟頁并加一個(gè)全局讀鎖,此刻數(shù)據(jù)庫實(shí)例只能SELECT,不能執(zhí)行任何類型的操作(會(huì)影響業(yè)務(wù)),再獲取BINLOG、GITD和備份對象的元數(shù)據(jù)信息,接著設(shè)置事務(wù)隔離級別和啟動(dòng)一致性快照,此時(shí)所有的支持事務(wù)的表(INNODB)數(shù)據(jù)均來自同一時(shí)間點(diǎn)。最后再釋放全局讀鎖,此刻數(shù)據(jù)庫實(shí)例可以執(zhí)行任何操作(正常情況,加全局讀鎖和釋放鎖的時(shí)間很短)。
2. 獲取備份對象:自定義函數(shù)、存儲(chǔ)過程、VIEW等。
3. 多線程 導(dǎo)出表「 SLEECT col1,col2,... 」。導(dǎo)出表分3種情況:已經(jīng)導(dǎo)出完成、還未導(dǎo)出和正在導(dǎo)出:
- 對于 已導(dǎo)出的 表, 不能 做DDL操作( 不支持SAVEPOINT );
- 對還未導(dǎo)出的表, 需要區(qū)分有沒有PK或UK:
沒有PK和UK, 還要根據(jù)DDL的操作方式: no-rebuild 方式的DDL執(zhí)行成功, rebuild 方式的DDL執(zhí)行失?。?nbsp;Table definition has changed),MyISAM引擎的表都能執(zhí)行成功;
有PK或UK,和正在導(dǎo)出的表情況一樣,原因是在獲取分片信息時(shí)需要查詢表的最大最小值。
- 對正在導(dǎo)出的表,DDL會(huì)出現(xiàn)MDL,此時(shí)對該表后續(xù)的查詢都會(huì)出現(xiàn)MDL,導(dǎo)致業(yè)務(wù)不可用(時(shí)間根據(jù)備份時(shí)長決定),直到該表導(dǎo)出完成。
4.所有對象的導(dǎo)出均轉(zhuǎn)存到 多個(gè)文件 (將表數(shù)據(jù)分塊導(dǎo)出成多個(gè)數(shù)據(jù)文件),完成備份。
3.5 小結(jié)
從上面各邏輯備份的流程中看到,在一致性備份下,所有表的DML操作不影響(除FTWRL短暫的時(shí)刻外),而DDL操作都存在一定的風(fēng)險(xiǎn)。所以在 邏輯備份期間,要盡量避免DDL操作 。
各邏輯備份工具的參數(shù)可以看官方文檔,對 比各工具之后,如表所示:
推薦使用的邏輯備份 ,需要具備的條件:支持一致性備份、行級別的 分片 多 線 程 導(dǎo)出 、 導(dǎo)出到多個(gè)文件(恢復(fù) 快 ), 延遲創(chuàng)建索引 和savepoint能力。從上面表中看到, mydumper 和 mysqlshell 中的dump方法能滿足較多的條件。
4. 總結(jié)
希望通過閱讀本文,能讓大家更清晰的了解邏輯備份的整個(gè)實(shí)現(xiàn)流程, 在選擇合適的邏輯備份時(shí)有幫助。