摘要:本文來自華為雲MySQL研發團隊,主要分享了MySQL備份工具Xtrabackup的備份過程、華為雲數據庫團隊對其做的優化改進,以及在使用中可能遇到的問題與解決方法。
本文分享自華為雲社區《華為雲帶你探秘Xtrabackup備份原理和常見問題分析》,作者:GaussDB 數據庫 。
本文來自華為雲MySQL研發團隊,主要分享了MySQL備份工具Xtrabackup的備份過程、華為雲數據庫團隊對其做的優化改進,以及在使用中可能遇到的問題與解決方法。文章討論的內容主要是針對華為雲RDS for MySQL, 以及用戶自建的社區版MySQL數據庫,希望有助於大家理解和使用Xtrabackup,以后面對Xtrabackup問題也更加從容。
一、Xtrabackup簡介
Xtrabackup是Percona團隊開發的用於MySQL數據庫物理熱備份的開源備份工具,具有備份速度快、支持備份數據壓縮、自動校驗備份數據、支持流式輸出、備份過程中幾乎不影響業務等特點,是目前各個雲廠商普遍使用的MySQL備份工具。
當前Xtrabackup存在兩個版本:Xtrabackup 2.4.x與8.0.x,分別用於備份MySQL 5.x與MySQL 8.0.x 版本。下面我們分別介紹 Xtrabackup如何備份MySQL社區版以及華為雲上的Xtrabackup的備份原理
二、社區版MySQL的Xtrabackup備份
Xtrabackup是為Percona MySQL設計的,同時也支持對官方社區版本MySQL進行備份,過程如下圖所示:
圖1:Xtrabackup備份官方MySQL流程示意
- 兼容性檢查:Xtrabackup社區版本只支持 MyISAM , InnoDB , CSV , MRG_MYISAM 四種存儲引擎的表,其他存儲引擎的表不會備份;在這一步中,通過查詢tables,若發現存在表的存儲引擎不是上述四種引擎之一,會打印warning, 表明Xtrabackup不會備份該表。
- 啟動redo后台備份線程:啟動redo后台備份線程,從備份實例的最近一次checkpoint LSN的位置開始備份所有增量的redo log,一直持續到備份任務結束。
- 加載所有的innodb表空間:打開並掃描所有innodb表的數據文件,檢查所有表空間的第一個頁面,初始化所有表的內存結構。
- 備份innodb表:遍歷步驟3所構建的表的內存結構,備份每一個innodb表的數據文件,備份的過程中會檢查每個頁面的數據是否正確。
- 加備份鎖 FLUSH TABLES WITH READ LOCK (FTWRL):FTWRL鎖是MySQL實例級的讀鎖,加鎖過程復雜,且加鎖之后,所有表的所有更新操作以及DDL都會堵塞。
- 備份非innodb表:因為在步驟5我們已經對實例加了讀鎖,因此,此時備份非innodb表是安全的,此時一定沒有寫業務。
- 記錄binlog當前的GTID信息:請注意,此時我們仍持有全局讀鎖。這一步主要是方便我們使用該備份集快速地創建出備機。
- 停止redo備份線程。
- 釋放鎖資源,備份結束。
需要注意的是,Xtrabackup 2.4.x與8.0.x在第7、8這兩個步驟存在差異,這個差異有MySQL 8.0.x的原因,詳情我們在下文介紹。
三、華為雲RDS for MySQL備份
在備份社區版MySQL實例時,Xtrabackup會對實例加全局讀鎖(FTWRL),該鎖對數據庫的業務影響很大,嚴重時甚至會導致數據庫“掛起”,這對客戶來說是不可接受的。因此華為雲MySQL團隊對這個過程進行了優化,主要有兩點:
- 對MySQL 5.x以及0.x增加了備份鎖:LOCK TABLES FOR BACKUP
- 對MySQL 5.x新增了binlog鎖:LOCK BINLOG FOR BACKUP
優化之后,華為雲Xtrabackup對MySQL的備份過程如下:
圖2 Xtrabackup備份華為雲MySQL流程示意
與FTWRL鎖相比,備份鎖 LOCK TABLES FOR BACKUP對客戶實例影響很小,其加鎖過程簡單,加鎖期間innodb表的DML操作不受影響,但是非innodb表的所有的更新操作以及DDL操作仍然是不允許的。
備份完所有的表文件后,Xtrabackup需要獲取binlog GTID信息。
- 對於MySQL 5.x版本,Xtrabackup 2.4.x會執行 LOCK BINLOG FOR BACKUP 操作,對binlog加鎖,然后獲取GTID信息。
- 對於MySQL 8.0.x版本,華為雲Xtrabackup 8.0.x沿用官方的一致性備份點查詢方法。Xtrabackup查詢log_status 時,MySQL服務器會分別對redo log, binlog等加輕量級鎖,獲取一致性備份點,這個過程是非常短暫的,對實例的運行幾乎沒有影響。MySQL 8.0.x的備份一致性點,會告訴我們一致性的redo log LSN以及binlog的GTID;查詢完備份一致點后,Xtrabackup會備份最后一個binlog文件,用於恢復時仲裁事務是否需要回滾;最后,redo log備份線程任務會在其讀取到的redo log的LSN大於查詢到的備份一致性點的redo log LSN處停止。
由於Xtrabackup 2.4.x與8.0.x在處理binlog時存在差異,恢復過程也存在差異,我們會在后續文章中詳細闡述。
四、常見問題與解決方法
華為雲已經使用Xtrabackup為公司幾乎所有的MySQL實例提供備份服務,在使用過程中,我們積極與社區保持聯系,向Percona社區報告使用過程中的一些問題,幫助Xtrabackup向更好的方向演進。此外,對於發現的一些致命問題,若社區未能及時修復,華為雲數據庫團隊會進行及時修復以保證備份數據的正確性。
下面是我們總結在使用Xtrabackup備份過程各個階段可能遇到的問題,分析其原因以及對應的解決方法,
1. 兼容性檢查階段
- 問題現象:Xtrabackup啟動后,立即長時間“掛起”,查看日志發現redo log備份線程也沒有啟動。
原因:Xtrabackup兼容性檢查時無法獲取MDL鎖。Xtrabackup兼容性檢查是通過查詢 imformation_schema.tables這個插件表實現:
“SELECT CONCAT(table_schema, '/', table_name), engine FROM information_schema.tables WHERE engine NOT IN ('MyISAM', 'InnoDB', 'CSV', 'MRG_MYISAM') AND table_schema NOT IN ('performance_schema', 'information_schema', 'mysql')”
在查詢每張表時,需要獲取對應表的MDL鎖,如果此時MySQL實例中存在長時間的DML或者DDL 語句,或者更嚴重者出現了MDL死鎖,上面的查詢會一直堵塞在等待MDL鎖階段,此時 Xtrabackup會長時間“掛起”。
解決辦法:若等待鎖的原因只是因為其他SQL語句的堵塞,等待其他SQL執行完成即可;若是發生了死鎖,此時需要分析出死鎖原因,將死鎖解除;華為雲RDS for MySQL提供了MDL鎖視圖功能,可以很好地幫助用戶分析業務的MDL死鎖。
2.redo log備份階段
- 問題現象1:redo log回卷,備份失敗,Xtrabackup報如下錯誤信息:
“xtrabackup: error:it looks like InnoDB log has wrapped around before xtrabackup could process all records due to either log copying being too slow, or log files being too small.\n");”
原因:在備份的過程中,如果主機業務負載很高,導致redo log寫入的速度很快,會發生Xtrabackup的redo log備份線程的備份速度小於redo log的寫入速度,因為MySQL redo log文件寫入使用了 round-robin的方式,使得新寫入的日志覆蓋了之前寫入卻還未備份的日志,因此備份失敗。
解決辦法:推薦在業務低峰期進行備份,或者增大redo log的文件大小。
- 問題現象2:備份因DDL操作失敗,錯誤信息如下:
“An optimized (without redo logging) DDLoperation has been performed. All modified pages may not have been flushed to the disk yet.
PXB will not be able take a consistent backup. Retry the backup operation”
原因: 備份過程中MySQL實例發生了創建索引的DDL操作,因為創建索引不會寫redo,若繼續備份會引起數據不一致問題,所以Xtrabackup在這種場景中備份失敗是預期行為。
解決辦法:不要在備份過程中創建索引,如果確實需要,建議在建表語句中直接帶上索引,或者使用 lock-ddl 參數進行備份(阻塞實例上新的DDL操作)。
- 問題現象3:undo truncate導致備份失敗,Xtrabackup錯誤信息如下:
“An undo ddl truncation (could be automatic) operation has been performed.”
原因:在Xtrabackup備份期間,如果MySQL實例發生undo truncate時,有可能會出現寫入新 undo文件(space id不同)的undo日志丟失導致恢復出來的數據存在問題。官方在Xtrabackup 8.0.14版本(基於MySQL 8.0.21)對該問題進行了修復,修復方法是redo備份線程,解析redo log時若發現該操作是undo log的truncate操作,則會備份失敗。遺憾的是,該修復並沒有完全解決問題,在以下兩種場景中,社區版本的Xtrabackup仍可能會發生恢復出來的數據存在不一致的現象:
- MySQL版本低於MySQL 8.0.21;
- 用戶在備份過程中,自己創建了新的undo tablespace。
解決辦法:在備份期間關閉undo tablespace的truncate操作,並禁止用戶創建undo tablespace, 能夠有效地防止備份數據恢復出來不一致的問題;另外華為雲Xtrabackup對這個問題進行了進一步的修復,可以有效地防止此類現象發生。
3.加載表空間階段
- 問題現象1:Xtrabackup報錯:Too many open files
原因:操作系統允許同時打開的文件數量是有限的,Xtrabackup在load tablespace階段會同時打開所有的表文件,如果Xtrabackup打開的表的個數超過了該限制,則會備份失敗。
解決辦法:調大操作系統,允許同時打開最大文件數的配置,或者使用 lock-ddl 參數(阻塞實例上新的DDL操作)。
- 問題現象2:rename table導致備份失敗,錯誤信息如下:
“Trying to add tablespace 'xxxx' with id xxx to the tablespace memory cache, but tablespace xxxx already exists in the cache!;”
原因:在Xtrabackup打開表空間的全過程是沒有加鎖的,如果發生了rename table有概率會發生重復加載相同的表空間,此時Xtrabackup會檢測到重復的tablespace id,因此備份失敗。
解決辦法:一般來說,加載表空間是一個很快的操作,rename table並不是一個很頻繁的操作,這種情況重試即可(Percona Xtrabackup 2.4.x僅支持單線程加載表空間,華為雲Xtrabackup支持多線程加載表空間)。
4.備份innodb表階段
- 問題現象:innodb表數據文件損壞,備份失敗,錯誤信息如下:
“xtrabackup: Database page corruption detected at page xxxx, retrying.”
原因:Xtrabackup在備份innodb表數據文件時,會檢查每個頁面的checksum,如果發現checksum不對,則備份失敗,這時說明MySQL實例的數據已經發生了損壞(例如磁盤靜默錯誤)。
解決辦法:需要通過恢復前一次的備份數據或者其他的辦法將數據進行修復之后,備份才能成功,在后續的文章中,我們也會詳細介紹數據修復辦法。
五、結語
本文主要對比介紹了Xtrabackup備份原理,備份社區版MySQL以及華為雲對其的改進,並分享了Xtrabackup常見問題的排查與解決,后續我們也會為大家帶來更深入的分析,更實用的使用技巧,希望對大家理解和使用Xtrabackup有幫助。我們也將持續為客戶提供更好的數據庫服務,並時刻守護客戶的數據安全。
最后,告訴大家一個好消息,雲數據庫MySQL包年19.9元起,助力企業無憂上雲,歡迎大家前來體驗