本文由 網易雲 釋出。
我們把資料庫裡部分或全部 Schema和資料遷移到另一個例項的行為稱為例項遷移,將匯出資料的例項稱為源例項,匯入資料的例項稱為目標例項。
根據遷移資料庫型別的不同,可以分為同種資料庫之間的遷移,如從 MySQL遷到 MySQL;和跨資料庫型別的遷移,如從 Oracle遷移到 MySQL等。
本文將介紹網易雲基礎服務RDS例項遷移功能的實現,並探討如何高效完成例項遷移任務。
使用場景
那麼,為什麼要進行 MySQL例項遷移呢?不同場景下分別該如何遷移?例項遷移的場景歸納起來主要有以下幾種:
1、從自建例項遷移到 RDS:
在雲服務還未充分推廣時,存在大量自建資料庫例項,以網易公司為例,在公司業務全面上雲之前,網易部落格、網易郵箱等產品的數百個 MySQL例項都是直接部署在物理伺服器上,而隨著業務的擴充套件,必然要對例項進行擴容、升規格等操作。
相比自建例項,RDS例項在故障處理、線上擴容、升級等方面存在著天然的優勢,所以,目前,網易絕大部分網際網路產品的資料庫均已使用例項遷移功能將例項遷移到了 RDS上;
2、從其他公有云平臺遷移到 RDS:
網易雲基礎服務RDS推出以來,有很多使用者將部署在其他公有云平臺上的 MySQL例項遷移到網易雲基礎服務RDS上。我們對例項遷移功能進行統計發現,有 50%是用於遷移其他公有云的 MySQL例項。
例項遷移技術實現
在設計例項遷移功能前,我們對業界公有云進行了充分調研,僅有兩家主流公有云平臺提供例項遷移功能,那麼為什麼僅兩家呢,主要是因為提供線上例項遷移功能需要解決一系列問題,概括起來有以下幾點:
1.如何快速地對源例項進行一致性資料備份?
2.如何處理備份過程中對源例項業務的影響?
3.如何快速地將備份匯入到目標例項?
4.如何同步源例項的增量資料到目標例項?
5.如何確保例項遷移高效完成?
下面逐條解析網易雲基礎服務 RDS是如何解決這些難題的。
1 多執行緒邏輯備份
我們解決第一個問題的方法是採用多執行緒邏輯備份的方式來進行源例項一致性資料匯出。
MySQL的資料備份工具有很多,邏輯備份工具包括經典的 mysqlpump,MySQL 5.7版本新推出的 mysqlpump,Percona開源工具 mydumper;物理備份主要是 Percona的 xtrabackup工具。
俗話說沒有最好的,只有最合適的,那麼在這些備份工具中,哪種工具最適合用於進行例項遷移呢?我們的答案是 mydumper。
首先我們排除了 xtrabackup,雖然物理備份在效能上有優勢,但其無法遠端備份源例項,在進行例項遷移時,我們不可能要求使用者賦予操作源例項伺服器的許可權,尤其在遷移其他公有云平臺的 RDS例項時更不現實。此外,物理備份產生的備份資料往往比邏輯備份匯出的資料更大,因為 xtrabackup直接拷貝物理檔案,而邏輯備份是匯出 SQL語句。
下面是我們對幾種備份工具的對比測試結果,可供參考:
排除了物理備份後,還有三個選項:mysqldump、mysqlpump和 mydumper。我們最終選擇了 mydumper,因為 mydumper是多執行緒的。
等等!瞭解 MySQL的同學會質疑,mysqlpump也是多執行緒的啊?對,mysqlpump的多執行緒思想甚至比 mydumper更先進(詳見參考文獻1和2),但 mysqlpump是表級的併發,且還不成熟,而 mydumper是記錄級的併發,針對單個大表的場景,更容易發揮多執行緒優勢。
也許你會好奇,mydumper是如何實現記錄級的多執行緒一致性備份的,其備份流程圖如下:
mydumper由主執行緒和多個工作執行緒配合完成資料一致性備份,主執行緒執行 FTWRL或 Lock Tables tablelist Read阻塞寫操作來建立一致性備份點並記錄當前 BinLog和 GTID。工作執行緒在主執行緒仍持有鎖的情況下將各 session的事務級別設定為可重複讀(repeatable-read),並開始進行快照讀。由於此時各表無法進行資料寫入或更新,所以工作執行緒快照讀的資料就是主執行緒建立一致性備份點的資料。待所有工作執行緒均已開始快照讀後,如果不存在 MyISAM等非事務性表,主執行緒即可釋放讀鎖(mydumper原理的詳細分析詳見參考文獻3)。
2 業務負載監控與調整
無論是物理備份還是邏輯備份,都會或多或少地對資料庫線上業務造成影響。如何處理備份過程中對源例項業務的影響是我們需要解決的第二個問題。
網易雲基礎服務RDS例項的設計原則是線上業務永遠比遷移任務更重要。由於無法有效瞭解源例項所在伺服器層的監控資料,我們在 MySQL資料庫層進行大量的優化來降低影響。包括引入持鎖時間超時機制、基於業務負載智慧調整匯出併發度和 InnoDB Buffer Pool(BP)汙染控制等。
如前所述,為了能夠得到一致性的資料,各種備份工具,包括 xtrabackup和 mydumper,都需要有個短暫給源例項加讀鎖的過程,正常情況下短暫,但也會有例外,如源例項中存在資料量較大的 MyISAM表時,持鎖時間會變長。
為了能夠避免持鎖時間過長導致業務的寫操作被阻塞,使用網易雲基礎服務(蜂巢) RDS進行例項遷移時,使用者可以選擇允許持有讀鎖的最長時間,如下圖所示,如果超過該閾值時間,會無條件解鎖並讓遷移操作失敗,使用者可以選擇在業務低峰期進行重試。
在順利加鎖建立一致性快照並解鎖後,就進入到各種 Schema和表資料的匯出環節,使用者應根據源例項的線上業務負載和例項的伺服器 IO能力來合理選擇匯出資料的併發執行緒數,如上圖所示。
業務負載並不總是可以預測的,但業務總是最重要的,那麼當短暫的業務高峰上來時,我們希望將伺服器有限的 IO能力還給業務,而不是用在遷移上。網易雲基礎服務(蜂巢) RDS提供了負載監控閾值選項,在業務負載超過該閾值時,會暫停遷移操作,直到負載重新低於閾值。如果使用者選擇了多執行緒匯出,則能夠根據業務負載動態調整執行緒個數,確保在業務優先的前提下儘可能快速地完成資料匯出操作。
下圖為基於業務負載自適應調整匯出執行緒的例子。
在邏輯匯出的過程中,還會根據使用者提供的遷移賬號許可權,選擇性調整 InnoDB BP引數來最大限度減小遷移連線的查詢操作對 BP熱點資料的汙染。儘可能將因遷移而進入 BP的資料保留在 BP的 LRU List冷資料一側,並儘快被替換出 BP(詳見參考文獻4)。當然,設定 BP的引數需要賬號有 Super許可權,對於公有云上的源例項,無法進行該項優化。
3 多執行緒資料匯入
使用與 mydumper配套的多執行緒恢復工具 myloader來將備份的資料匯入到目標 RDS例項上,myloader執行流程如下圖所示。
由於此時目標例項沒有負載,所以可以儘可能調大匯入併發執行緒數,將目標例項的 IO能力吃滿。此外,在資料匯入時,我們通過關閉 slow log和 binary log,將 innodb_flush_log_at_trx_commit設定為 0來最大限度提高匯入效能,在完成資料匯入後再將對應的引數調整為原值。這是我們解決第三個問題的方法。
4 並行過濾複製
在完成資料匯入後,對於全量遷移的場景,遷移就結束了。若選擇增量遷移,還需將資料匯出和匯入時在源例項上產生的增量資料(Update/Delete)也遷移到目標例項,我們採用 MySQL複製的方式來同步這些資料。
由於 MySQL 5.5、5.6和 5.7版本的複製存在較大差別,我們根據源例項的版本選擇對應的目標例項版本。對於 MySQL 5.5及更低版本的源例項,選擇網易開源 MySQL版本 InnoSQL 5.5.30作為目標 RDS例項版本,對於 MySQL 5.6和 5.7,選擇 InnoSQL 5.7.12為目標例項版本。進行上述版本配對的原因在於:
一是希望使用者儘可能採用 MySQL最新的穩定版本 5.7,因為 MySQL 5.7是有史以來最好的版本,帶來了眾多優秀的特性,包括基於 GTID的複製、sys表等,同時相比之前的版本,解決和優化了大量缺陷或不足。
二是能夠更加方便地配置複製。MySQL 5.7版本提供了基於 GTID和基於 BinLog兩套複製機制,針對源例項不同的複製配置,能無縫適配。使用者在遷移源例項時,可選擇遷移例項上全部資料庫,也可選擇僅遷移部分資料庫,MySQL 5.7版本可使用新增的 “CHANGE REPLICATION FILTER” 語法線上進行過濾複製設定而無需重啟 mysqld。
由於 MySQL 5.5及更低版本無法滿足 MySQL 5.7版本與之建立複製所需的例項 UUID,所以目標例項使用 InnoSQL 5.5.30版本。當然,相比社群版 MySQL 5.5.30,InnoSQL 5.5.30實現了線上過濾複製功能。
我們採用並行複製技術來提高增量資料同步的效率,快速縮短主從複製延遲。由於 MySQL 5.6版本 GTID特性並不完善,在將其遷移到 MySQL 5.7版本時,採用基於 DATABASE的並行複製方式,避免 LOGICAL_CLOCK並行複製時由於 GTID EVENT未記錄並行資訊導致複製出錯的 bug。這樣,第四個問題也得到了解決。
如何高效完成遷移
相信大家都認同,例項遷移是個重型操作,誰都不會閒來無事對線上資料庫來一把例項遷移。既然決定要進行例項遷移,那麼就希望能夠一次性完成遷移,避免來回折騰。
如何確保高效地遷移就顯得尤為重要,使用者需先進行遷移評估並完成準備工作,網易雲基礎服務RDS通過遷移預檢查、提供出錯重試等措施來提高遷移成功率。
1、遷移評估和準備
使用者首先需在遷移前做好評估工作,包括選擇業務低峰期進行遷移,這樣既最小化對業務的影響同時也能夠提高遷移速度;確認業務連線資料庫的配置能夠進行一次性切換,縮短切換所需時間,同時避免部分業務邏輯連線源庫,另一部分連線目標庫導致資料不一致;其次,根據所遷移的資料量,合理選擇目標例項的儲存空間,避免因為目標例項空間不足導致失敗;最後,還需要建立滿足遷移要求的資料庫賬號。
2、預檢查
我們希望在開始遷移前就發現所有可能引起遷移失敗的因素並糾正。遷移預檢查是重要手段,主要包括使用者在源例項建立的遷移 MySQL賬號許可權檢查、MySQL引數設定檢查。
遷移許可權檢查用於確認遷移賬號是否能夠順利完成遷移操作,主要包括對資料庫定義、表定義,檢視、觸發器、儲存過程和函式等 Schema的檢視許可權;對所選中資料庫中表的 Lock Table許可權,及表中資料 Select許可權;如果選擇增量遷移,則還需檢查賬號是否具備 Replication slave和 Replication client許可權等。通過查詢源例項的 MySQL、information_schema或 performance_schema等系統庫來檢查遷移所需許可權。
MySQL引數檢查主要針對需要做增量資料同步的場景,如果使用者選擇增量遷移,源例項需正確設定 server_id和 log_bin等引數。如果在預檢查中發現錯誤,會給出明確的提示,引導使用者進行引數調整後再重新進行預檢查。
3、錯誤重試
在遷移過程中,提供了進度顯示功能,如下所示:
遷移的每個階段都會有帶進度條的百分比顯示,並週期性自動重新整理。同時還會顯示整體的遷移進度,方便使用者隨時檢視。若在資料匯出或匯入等階段發生錯誤,則會提示錯誤資訊,一般出現遷移錯誤的原因主要是由於存在 MyISAM表導致持鎖時間超時,根據錯誤資訊可以對遷移引數進行鍼對性修改後進行重試,無需重新開始遷移。
4、結束遷移
在確認目標例項和源例項間沒有複製延遲後,就可以結束遷移並將業務的 IP切換為目標例項 IP。當然,在 IP切換前,請確認已經在網易雲基礎服務 RDS例項上建立業務訪問所需的資料庫賬號並賦予合適的許可權。
瞭解網易雲:
網易雲官網:www.163yun.com/
新使用者大禮包:www.163yun.com/gift
網易雲社群:sq.163yun.com/