(image via https://pixabay.com/en/military-stealth-bomber-refueling-602729/ )mysql
在上篇文章 從 SQL Server 到 MySQL (一):異構數據庫遷移 - Log4D 中,咱們給你們介紹了從 SQL Server 到 MySQL 異構數據庫遷移的基本問題和全量解決方案。 全量方案能夠知足一部分場景的需求,可是這個方案仍然是有缺陷的: 遷移過程當中須要停機,停機的時長和數據量相關。 對於核心業務來講,停機就意味着損失。 好比用戶中心的服務,以它的數據量來使用全量方案,會致使遷移過程當中停機若干個小時。 而一旦用戶中心中止服務,幾乎全部依賴於這個中央服務的系統都會停擺。git
能不能作到無縫的在線遷移呢?系統不須要或者只須要極短暫的停機? 做爲有追求的技術人,咱們必定要想辦法解決上面的問題。github
針對 Oracle 到 MySQL,市面上已經有比較成熟的解決方案 - alibaba 的 yugong 項目。 在解決 SQL Server 到 MySQL 在線遷移以前,咱們先研究一下 yugong 是如何作到 Oracle 的在線遷移。web
下圖是 yugong 針對 Oracle 到 MySQL 的增量遷移流程:sql
這其中有四個步驟:數據庫
Oracle 物化視圖(Materialized View)是 Oracle 提供的一個機制。 一個物化視圖就是主庫在某一個時間點上的複製,能夠理解爲是這個時間點上的 Snapshot。 當主庫的數據持續更新時,物化視圖的更新能夠經過獨立的批量更新完成,稱之爲 refreshes
。 一批 refreshes
之間的變化,就對應到數據庫的內容變化狀況。 物化視圖常常用來將主庫的數據複製到從庫,也經常在數據倉庫用來緩存複雜查詢。緩存
物化視圖有多種配置方式,這裏比較關心刷新方式和刷新時間。 刷新方式有三種:服務器
刷新機制有兩種模式: Refresh-on-commit 和 Refresh-On-Demand。微信
Oracle 基於物化視圖,就能夠完成增量數據的獲取,從而知足阿里的數據在線遷移。 將這個技術問題泛化一下,想作到在線增量遷移須要有哪些特性? 咱們獲得以下結論(針對源數據庫):數據結構
回到咱們面臨的問題上來,SQL Server 是否有這個機制知足這三個特性呢? 答案是確定的,SQL Server 官方提供了 CDC 功能。
什麼是 CDC? CDC 全稱 Change Data Capture,設計目的就是用來解決增量數據的。 它是 SQL Server 2008 新增的特性, 在這以前只能使用 SQl Server 2005 中的 after insert
/ after delete
/ after update
Trigger 功能來得到數據變化。
CDC 的工做原理以下:
當數據庫表發生變化時候,Capture process 會從 transaction log 裏面獲取數據變化, 而後將這些數據記錄到 Change Table 裏面。 有了這些數據,用戶能夠經過特定的 CDC 查詢函數將這些變化數據查出來。
CDC 的核心數據就是那些 Change Table 了,這裏咱們給你們看一下 Change Table 長什麼樣,能夠有個直觀的認識。
經過如下的函數打開一張表(fruits)的 CDC 功能。
-- enable cdc for db
sys.sp_cdc_enable_db;
-- enable by table
EXEC sys.sp_cdc_enable_table @source_schema = N'dbo', @source_name = N'fruits', @role_name = NULL;
-- list cdc enabled table
SELECT name, is_cdc_enabled from sys.databases where is_cdc_enabled = 1;
複製代碼
至此 CDC 功能已經開啓,若是須要查看哪些表開啓了 CDC 功能,可使用一下 SQL:
-- list cdc enabled table
SELECT name, is_cdc_enabled from sys.databases where is_cdc_enabled = 1;
複製代碼
開啓 CDC 會致使產生一張 Change Table 表 cdc.dbo_fruits_CT
,這張表的表結構如何呢?
.schema cdc.dbo_fruits_CT
name default nullable type length indexed
-------------- ------- -------- ------------ ------ -------
__$end_lsn null YES binary 10 NO
__$operation null NO int 4 NO
__$seqval null NO binary 10 NO
__$start_lsn null NO binary 10 YES
__$update_mask null YES varbinary 128 NO
id null YES int 4 NO
name null YES varchar(255) 255 NO
複製代碼
這張表中以 __
開頭的字段是 CDC 所記錄的元數據,id
和 name
是 fruits 表的原始字段。 這意味着 CDC 的表結構和原始表結構是一一對應的。
接下來咱們作一些業務操做,讓數據庫的數據發生一些變化,而後查看 CDC 的 Change Table:
-- 1 step
DECLARE @begin_time datetime, @end_time datetime, @begin_lsn binary(10), @end_lsn binary(10);
-- 2 step
SET @begin_time = '2017-09-11 14:03:00.000';
SET @end_time = '2017-09-11 14:10:00.000';
-- 3 step
SELECT @begin_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than', @begin_time);
SELECT @end_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', @end_time);
-- 4 step
SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_fruits(@begin_lsn, @end_lsn, 'all');
複製代碼
這裏的操做含義是:
查詢出來的數據以下所示:
__$start_lsn __$end_lsn __$seqval __$operation __$update_mask id name
-------------------- ---------- -------------------- ------------ -------------- -- ------
0000dede0000019f001a null 0000dede0000019f0018 2 03 1 apple
0000dede000001ad0004 null 0000dede000001ad0003 2 03 2 apple2
0000dede000001ba0003 null 0000dede000001ba0002 3 02 2 apple2
0000dede000001ba0003 null 0000dede000001ba0002 4 02 2 apple3
0000dede000001c10003 null 0000dede000001c10002 2 03 3 apple4
0000dede000001cc0005 null 0000dede000001cc0002 1 03 3 apple4
複製代碼
能夠看到 Change Table 已經如實的記錄了咱們操做內容,注意 __$operation
表明了數據庫操做:
根據查出來的數據,咱們能夠重現這段時間數據庫的操做:
id
爲 1 / 2 的兩條數據id
爲 2 的數據id
爲 3 的數據id
爲 3 的數據有了 CDC 這個利器,終於意味着咱們的方向是沒有問題的,咱們終於稍稍吁了一口氣。 但除了瞭解原理和使用方式,咱們還須要深刻了解 CDC 的工做機制,對其進行壓測、調優, 瞭解其極限和邊界,不然一旦線上出現不可控的狀況,就會對業務帶來巨大損失。
咱們先看看 CDC 的工做流程,就能夠知道有哪些核心參數能夠調整:
上圖是 CDC Job 的工做流程:
maxscans
)maxtrans
pollinginterval
這三個參數平衡着 CDC 的服務器資源消耗、吞吐量和延遲, 根據具體場景,好比大字段,寬表,BLOB 表,能夠調整從而達到知足業務須要。 他們的默認值以下:
maxscan
默認值 10maxtrans
默認值 500pollinginterval
默認值 5 秒掌握了可以調整的核心參數,咱們即將對 CDC 進行了多種形式的測試。 在壓測以前,咱們還須要肯定關鍵的健康指標,這些指標有:
出於篇幅考慮,咱們沒法將全部測試結果貼出來, 這裏放一個在併發 30 下面插入一百萬數據(隨機數據)進行展現:
測試結論是,在默認的 CDC 參數下面:
CDC 的開啓/關閉過程當中會致使若干個 Process Block, 大流量請求下面(15k TPS)過程會致使約 20 個左右 Process Block。 這個過程當中對服務器的 IO / CPU 無明顯波動, 開啓/關閉瞬間會帶來 mssql.sql-statistics.sql-compilations 劇烈波動。 CDC 開啓後,在大流量請求下面對 QPS / Page IO 無明顯波動, 對服務器的 IO / CPU 也無明顯波動, CDC 開啓後能夠在 16k TPS 下正常工做。
若是對性能不達標,官方有一些簡單的優化指南:
OK,截目前位置,咱們已經具有了 CDC 這個工具,可是這僅僅提供了一種可能性, 咱們還須要一個工具將 CDC 的數據消費出來,並喂到 MySQL 裏面去。
好在有 yugong。 Yugong 官方提供了 Oracle 到 MySQL 的封裝,而且抽象了 Source / Target / SQL Tempalte 等接口, 咱們只要實現相關接口,就能夠完成從 SQL Server 消費數據到 MySQL 了。
這裏咱們不展開,我還會花專門的一篇文章講如何在 yugong 上面進行開發。 能夠提早劇透一下,咱們已經將支持 SQL Server 的 yugong 版本開源了。
數據庫遷移這樣的項目,咱們不只僅要保證單向從 SQL Server 到 MySQL 的寫入, 同時要從 MySQL 寫入 SQL Server。
這個流程一樣考慮增量寫入的要素:增量消費,延遲,冪等一致性。
MySQL 的 binlog 能夠知足這三個要素,須要注意的是,MySQL binlog 有三種模式, Statement based,Row based 和 Mixed。只有 Row based 才能知足冪等一致性的要求。
確認理論上可行以後,咱們同樣須要一個工具將 binlog 讀取出來,而且將其轉化爲 SQL Server 能夠消費的數據格式,而後寫入 SQL Server。
咱們目光轉到 alibaba 的另一個項目 Canal。 Canal 是阿里中間件團隊提供的 binlog 增量訂閱 & 消費組件。 之因此叫組件,是因爲 Canal 提供了 Canal-Server 應用和 Canal Client Library, Canal 會模擬成一個 MySQL 實例,做爲 Slave 鏈接到 Master 上面, 而後實時將 binlog 讀取出來。 至於 binlog 讀出以後想怎麼使用,權看用戶如何使用。
咱們基於 Canal 設計了一個簡單的數據流,在 yugong 中增長了這麼幾個功能:
Canal Server 中的 binlog 只能作一次性消費, 內部實現是一個 Queue, 爲了知足咱們能夠重複消費數據的能力,咱們還額外設計了一個環節,將 Canal 的數據放到 Queue 中,在將來任意時間能夠重複消費數據。 咱們選擇了 Redis 做爲這個 Queue,數據流以下。
數據庫的遷移在去 Windows 中,是最不容得出錯的環節。 應用是無狀態的,出現問題能夠經過回切較快地回滾。 但數據庫的遷移就須要考慮周到,作好資源準備,發佈流程, 故障預案處理。
考慮到多個事業部都須要經歷這個一個過程,咱們項目組將每個步驟都固化下來, 造成了一個最佳實踐。咱們的遷移步驟以下,供你們參考:
大階段 | 階段 | 事項 | 是否完成 | 負責人 | 耗時 | 開始時間 | 完成時間 | 備註 |
---|---|---|---|---|---|---|---|---|
白天 | 存量數據階段 | 建立 MySQL 數據庫,準備相關帳號資源 | DBA | |||||
開啓 CDC | DBA | |||||||
從 Slave SQLServer dump 一份 snapshot 到 Backup SQL Server | DBA | |||||||
Backup SQL Server 消費數據, ETL 到 MySQL | DBA | |||||||
增量數據階段 | 確認 ETL 數據已經消費完成,檢查數據總條數 | DBA | ||||||
從 Slave SQLServer 開始消費 CDC 數據,持續寫入 MySQL | DBA | |||||||
使用 yugong 檢查一天內數據的一致性 | DBA | |||||||
檢查不一致的數據,10 分鐘以後人工進行檢查,確認是 CDC 延遲帶來的問題 | DBA | |||||||
檢查數據總量條目 | DBA | |||||||
使用 yugong 對抽樣表進行全量檢查 | DBA | |||||||
凌晨 | 應用發佈階段 | 中止 SQL Server 的應用 | 技術經理 | |||||
檢查沒有鏈接進入 SQL Server | DBA | |||||||
使用 yugong 檢查一天內數據的一致性 | DBA | |||||||
檢查數據總量條目 | DBA | |||||||
啓用基於 MySQL 的應用 | 運維 | |||||||
測試階段 | 測試應用是否正常,迴歸全部功能 | QA | ||||||
(臨時新增)測試 ReadOnly DB 的應用訪問狀況 | QA | |||||||
完成階段 | 接入流量 | 運維 | ||||||
(可選)回滾階段 | 發現問題,直接將應用切回 SQL Server | 運維 | ||||||
過後進行數據審計,進行新增數據補償 | DBA | |||||||
(可選)回滾過程當中,使用 Canal 讀取 binlog,並使用 Canal Client 重放到 SQL Server | DBA |
原文連接: https://blog.alswl.com/2018/05/sql-server-migration-2/
歡迎關注個人微信公衆號:窺豹
3a1ff193cee606bd1e2ea554a16353ee