從 SQL Server 到 MySQL(二):在線遷移,空中換髮動機

flying-tanker

(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

yugong-oracle.png

這其中有四個步驟:數據庫

  1. 增量數據收集 (建立 Oracle 表的增量物化視圖)
  2. 進行全量複製
  3. 進行增量複製 (可並行進行數據校驗)
  4. 原庫停寫,切到新庫

Oracle 物化視圖(Materialized View)是 Oracle 提供的一個機制。 一個物化視圖就是主庫在某一個時間點上的複製,能夠理解爲是這個時間點上的 Snapshot。 當主庫的數據持續更新時,物化視圖的更新能夠經過獨立的批量更新完成,稱之爲 refreshes。 一批 refreshes 之間的變化,就對應到數據庫的內容變化狀況。 物化視圖常常用來將主庫的數據複製到從庫,也經常在數據倉庫用來緩存複雜查詢。緩存

物化視圖有多種配置方式,這裏比較關心刷新方式和刷新時間。 刷新方式有三種:服務器

  • Complete Refresh:刪除全部數據記錄從新生成物化視圖
  • Fast Refresh:增量刷新
  • Force Refresh:根據條件判斷使用 Complete Refresh 和 Fast Refres

刷新機制有兩種模式: Refresh-on-commit 和 Refresh-On-Demand。微信

Oracle 基於物化視圖,就能夠完成增量數據的獲取,從而知足阿里的數據在線遷移。 將這個技術問題泛化一下,想作到在線增量遷移須要有哪些特性? 咱們獲得以下結論(針對源數據庫):數據結構

  • 增量變化:支持增量得到增量數據庫變化
  • 延遲:獲取變化數據這個動做耗時須要儘量低
  • 冪等一致性:變化數據的消費應當作到冪等,即無論目標數據庫已有數據什麼狀態,均可以無差異消費

回到咱們面臨的問題上來,SQL Server 是否有這個機制知足這三個特性呢? 答案是確定的,SQL Server 官方提供了 CDC 功能。

CDC 的工做原理

什麼是 CDC? CDC 全稱 Change Data Capture,設計目的就是用來解決增量數據的。 它是 SQL Server 2008 新增的特性, 在這以前只能使用 SQl Server 2005 中的 after insert / after delete / after update Trigger 功能來得到數據變化。

CDC 的工做原理以下:

cdc-data-flow.png

當數據庫表發生變化時候,Capture process 會從 transaction log 裏面獲取數據變化, 而後將這些數據記錄到 Change Table 裏面。 有了這些數據,用戶能夠經過特定的 CDC 查詢函數將這些變化數據查出來。

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 所記錄的元數據,idname 是 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');
複製代碼

這裏的操做含義是:

  1. 定義存儲過程當中須要使用的 4 個變量
  2. begin_time / end_time 是 Human Readable 的字符串格式時間
  3. begin_lsn / end_lsn 是經過 CDC 函數轉化過的 Log Sequence Number,表明數據庫變動的惟一操做 ID
  4. 根據 begin_lsn / end_lsn 查詢到 CDC 變化數據

查詢出來的數據以下所示:

__$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 表明了數據庫操做:

  • 1 => 刪除
  • 2 => 插入
  • 3 => 更新前數據
  • 4 => 更新後數據

根據查出來的數據,咱們能夠重現這段時間數據庫的操做:

  • 新增了 id 爲 1 / 2 的兩條數據
  • 更新了 id 爲 2 的數據
  • 插入了 id 爲 3 的數據
  • 刪除了 id 爲 3 的數據

CDC 調優

有了 CDC 這個利器,終於意味着咱們的方向是沒有問題的,咱們終於稍稍吁了一口氣。 但除了瞭解原理和使用方式,咱們還須要深刻了解 CDC 的工做機制,對其進行壓測、調優, 瞭解其極限和邊界,不然一旦線上出現不可控的狀況,就會對業務帶來巨大損失。

咱們先看看 CDC 的工做流程,就能夠知道有哪些核心參數能夠調整:

Influence of capture job parameters

上圖是 CDC Job 的工做流程:

  • 藍色區域是一次 Log 掃描執行的最大掃描次數:maxscans number(maxscans
  • 藍色區域同時被最大掃描 transcation 數量控制:maxtrans
  • 淺藍色區域是掃描間隔時間,單位是秒:pollinginterval

這三個參數平衡着 CDC 的服務器資源消耗、吞吐量和延遲, 根據具體場景,好比大字段,寬表,BLOB 表,能夠調整從而達到知足業務須要。 他們的默認值以下:

  • maxscan 默認值 10
  • maxtrans 默認值 500
  • pollinginterval 默認值 5 秒

CDC 壓測

掌握了可以調整的核心參數,咱們即將對 CDC 進行了多種形式的測試。 在壓測以前,咱們還須要肯定關鍵的健康指標,這些指標有:

  • 內存:buffer-cache-hit / page-life-expectancy / page-split 等
  • 吞吐:batch-requets / sql-compilations / sql-re-compilations / transactions count
  • 資源消耗:user-connections / processes-blocked / lock-waits / checkpoint-pages
  • 操做系統層面:CPU 利用率、磁盤 IO

出於篇幅考慮,咱們沒法將全部測試結果貼出來, 這裏放一個在併發 30 下面插入一百萬數據(隨機數據)進行展現:

cdc-metrics.png

cdc-system-load.png

測試結論是,在默認的 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 下正常工做。

若是對性能不達標,官方有一些簡單的優化指南:

  • 調整 maxscan maxtrans pollinginterval
  • 減小在插入後馬上插入
  • 避免大批量寫操做
  • 限制須要記錄的字段
  • 儘量關閉 net changes
  • 沒任務壓力時跑 cleanup
  • 監控 log file 大小和 IO 壓力,確保不會寫爆磁盤
  • 要設置 filegroup_name
  • 開啓 sp_cdc_enable_table 以前設置 filegroup

yugong 的在線遷移機制

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 中增長了這麼幾個功能:

  • SQL Server 的寫入功能
  • 消費 Canal 數據源的功能

Canal Server 中的 binlog 只能作一次性消費, 內部實現是一個 Queue, 爲了知足咱們能夠重複消費數據的能力,咱們還額外設計了一個環節,將 Canal 的數據放到 Queue 中,在將來任意時間能夠重複消費數據。 咱們選擇了 Redis 做爲這個 Queue,數據流以下。

canal.png

最佳實踐

數據庫的遷移在去 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

Reference


原文連接: https://blog.alswl.com/2018/05/sql-server-migration-2/

歡迎關注個人微信公衆號:窺豹

窺豹

若是對你有幫助,給做者 ¥2 買張彩票吧。

3a1ff193cee606bd1e2ea554a16353ee

相關文章
相關標籤/搜索