TiDB Ecosystem Tools 原理解讀系列(三)TiDB-DM 架構設計與實現原理

PingCAP發表於2018-12-27

作者:張學程

簡介

TiDB-DM(Data Migration)是用於將資料從 MySQL/MariaDB 遷移到 TiDB 的工具。該工具既支援以全量備份檔案的方式將 MySQL/MariaDB 的資料匯入到 TiDB,也支援通過解析執行 MySQL/MariaDB binlog 的方式將資料增量同步到 TiDB。特別地,對於有多個 MySQL/MariaDB 例項的分庫分表需要合併後同步到同一個 TiDB 叢集的場景,DM 提供了良好的支援。如果你需要從 MySQL/MariaDB 遷移到 TiDB,或者需要將 TiDB 作為 MySQL/MariaDB 的從庫,DM 將是一個非常好的選擇。

架構設計

DM 是叢集模式的,其主要由 DM-master、DM-worker 與 DM-ctl 三個元件組成,能夠以多對多的方式將多個上游 MySQL 例項的資料同步到多個下游 TiDB 叢集,其架構圖如下:

1.png

  • DM-master:管理整個 DM 叢集,維護叢集的拓撲資訊,監控各個 DM-worker 例項的執行狀態;進行資料同步任務的拆解與分發,監控資料同步任務的執行狀態;在進行合庫合表的增量資料同步時,協調各 DM-worker 上 DDL 的執行或跳過;提供資料同步任務管理的統一入口。

  • DM-worker:與上游 MySQL 例項一一對應,執行具體的全量、增量資料同步任務;將上游 MySQL 的 binlog 拉取到本地並持久化儲存;根據定義的資料同步任務,將上游 MySQL 資料全量匯出成 SQL 檔案後匯入到下游 TiDB,或解析本地持久化的 binlog 後增量同步到下游 TiDB;編排 DM-master 拆解後的資料同步子任務,監控子任務的執行狀態。

  • DM-ctl:命令列互動工具,通過連線到 DM-master 後,執行 DM 叢集的管理與資料同步任務的管理。

實現原理

資料遷移流程

單個 DM 叢集可以同時執行多個資料同步任務;對於每一個同步任務,可以拆解為多個子任務同時由多個 DM-worker 節點承擔,其中每個 DM-worker 節點負責同步來自對應的上游 MySQL 例項的資料。對於單個 DM-worker 節點上的單個資料同步子任務,其資料遷移流程如下,其中上部的資料流向為全量資料遷移、下部的資料流向為增量資料同步:

2.png

在每個 DM-worker 節點內部,對於特定的資料同步子任務,主要由 dumper、loader、relay 與 syncer(binlog replication)等資料同步處理單元執行具體的資料同步操作。

  • 對於全量資料遷移,DM 首先使用 dumper 單元從上游 MySQL 中將表結構與資料匯出成 SQL 檔案;然後使用 loader 單元讀取這些 SQL 檔案並同步到下游 TiDB。

  • 對於增量資料同步,首先使用 relay 單元作為 slave 連線到上游 MySQL 並拉取 binlog 資料後作為 relay log 持久化儲存在本地,然後使用 syncer 單元讀取這些 relay log 並解析構造成 SQL 語句後同步到下游 TiDB。這個增量同步的過程與 MySQL 的主從複製類似,主要區別在於在 DM 中,本地持久化的 relay log 可以同時供多個不同子任務的 syncer 單元所共用,避免了多個任務需要重複從上游 MySQL 拉取 binlog 的問題。

資料遷移併發模型

為加快資料匯入速度,在 DM 中不論是全量資料遷移,還是增量資料同步,都在其中部分階段使用了併發處理。

對於全量資料遷移,在匯出階段,dumper 單元呼叫 mydumper 匯出工具執行實際的資料匯出操作,對應的併發模型可以直接參考 mydumper 的原始碼。在使用 loader 單元執行的匯入階段,對應的併發模型結構如下:

3.png

使用 mydumper 執行匯出時,可以通過 --chunk-filesize 等引數將單個表拆分成多個 SQL 檔案,這些 SQL 檔案對應的都是上游 MySQL 某一個時刻的靜態快照資料,且各 SQL 檔案間的資料不存在關聯。因此,在使用 loader 單元執行匯入時,可以直接在一個 loader 單元內啟動多個 worker 工作協程,由各 worker 協程併發、獨立地每次讀取一個待匯入的 SQL 檔案進行匯入。即 loader 匯入階段,是以 SQL 檔案級別粒度併發進行的。在 DM 的任務配置中,對於 loader 單元,其中的 pool-size 引數即用於控制此處 worker 協程數量。

對於增量資料同步,在從上游拉取 binlog 並持久化到本地的階段,由於上游 MySQL 上 binlog 的產生與傳送是以 stream 形式進行的,因此這部分只能序列處理。在使用 syncer 單元執行的匯入階段,在一定的限制條件下,可以執行併發匯入,對應的模型結構如下:

4.png

當 syncer 讀取與解析本地 relay log 時,與從上游拉取 binlog 類似,是以 stream 形式進行的,因此也只能序列處理。當 syncer 解析出各 binlog event 並構造成待同步的 job 後,則可以根據對應行資料的主鍵、索引等資訊經過 hash 計算後分發到多個不同的待同步 job channel 中;在 channel 的另一端,與各個 channel 對應的 worker 協程併發地從 channel 中取出 job 後同步到下游的 TiDB。即 syncer 匯入階段,是以 binlog event 級別粒度併發進行的。在 DM 的任務配置中,對於 syncer 單元,其中的 worker-count 引數即用於控制此處 worker 協程數量。

但 syncer 併發同步到下游 TiDB 時,存在一些限制,主要包括:

  • 對於 DDL,由於會變更下游的表結構,因此必須確保在舊錶結構對應的 DML 都同步完成後,才能進行同步。在 DM 中,當解析 binlog event 得到 DDL 後,會向每一個 job channel 傳送一個特殊的 flush job;當各 worker 協程遇到 flush job 時,會立刻向下遊 TiDB 同步之前已經取出的所有 job;等各 job channel 中的 job 都同步到下游 TiDB 後,開始同步 DDL;等待 DDL 同步完成後,繼續同步後續的 DML。即 DDL 不能與 DML 併發同步,且 DDL 之前與之後的 DML 也不能併發同步。sharding 場景下 DDL 的同步處理見後文。

  • 對於 DML,多條 DML 可能會修改同一行的資料,甚至是主鍵。如果併發地同步這些 DML,則可能造成同步後資料的不一致。DM 中對於 DML 之間的衝突檢測與處理,與 TiDB-Binlog 中的處理類似,具體原理可以閱讀《TiDB EcoSystem Tools 原理解讀(一)TiDB-Binlog 架構演進與實現原理》中關於 Drainer 內 SQL 之間衝突檢測的討論。

合庫合表資料同步

在使用 MySQL 支撐大量資料時,經常會選擇使用分庫分表的方案。但當將資料同步到 TiDB 後,通常希望邏輯上進行合庫合表。DM 為支援合庫合表的資料同步,主要實現了以下的一些功能。

table router

為說明 DM 中 table router(表名路由)功能,先看如下圖所示的一個例子:

5.png

在這個例子中,上游有 2 個 MySQL 例項,每個例項有 2 個邏輯庫,每個庫有 2 個表,總共 8 個表。當同步到下游 TiDB 後,希望所有的這 8 個表最終都合併同步到同一個表中。

但為了能將 8 個來自不同例項、不同庫且有不同名的表同步到同一個表中,首先要處理的,就是要能根據某些定義好的規則,將來自不同表的資料都路由到下游的同一個表中。在 DM 中,這類規則叫做 router-rules。對於上面的示例,其規則如下:

name-of-router-rule:
    schema-pattern: "schema_*"
    table-pattern: "table_*"
    target-schema: "schema"
    target-table: "table"
複製程式碼
  • name-of-router-rule:規則名,使用者指定。當有多個上游例項需要使用相同的規則時,可以只定義一條規則,多個不同的例項通過規則名進行引用。

  • schema-pattern:用於匹配上游庫(schema)名的模式,支援在尾部使用萬用字元(*)。這裡使用 schema_* 即可匹配到示例中的兩個庫名。

  • table-pattern:用於匹配上游表名的模式,與 schema-pattern 類似。這裡使用 table_* 即可匹配到示例中的兩個表名。

  • target-schema:目標庫名。對於庫名、表名匹配的資料,將被路由到這個庫中。

  • target-table:目標表名。對於庫名、表名匹配的資料,將被路由到 target-schema 庫下的這個表中。

在 DM 內部實現上,首先根據 schema-pattern / table-pattern 構造對應的 trie 結構,並將規則儲存在 trie 節點中;當有 SQL 需要同步到下游時,通過使用上游庫名、表名查詢 trie 即可得到對應的規則,並根據規則替換原 SQL 中的庫名、表名;通過向下遊 TiDB 執行替換後的 SQL 即完成了根據表名的路由同步。有關 router-rules 規則的具體實現,可以閱讀 TiDB-Tools 下的 table-router pkg 原始碼

column mapping

有了 table router 功能,已經可以完成基本的合庫合表資料同步了。但在資料庫中,我們經常會使用自增型別的列作為主鍵。如果多個上游分表的主鍵各自獨立地自增,將它們合併同步到下游後,就很可能會出現主鍵衝突,造成資料的不一致。我們可看一個如下的例子:

6.png

在這個例子中,上游 4 個需要合併同步到下游的表中,都存在 id 列值為 1 的記錄。假設這個 id 列是表的主鍵。在同步到下游的過程中,由於相關更新操作是以 id 列作為條件來確定需要更新的記錄,因此會造成後同步的資料覆蓋前面已經同步過的資料,導致部分資料的丟失。

在 DM 中,我們通過 column mapping 功能在資料同步的過程中依據指定規則對相關列的資料進行轉換改寫來避免資料衝突與丟失。對於上面的示例,其中 MySQL 例項 1 的 column mapping 規則如下:

mapping-rule-of-instance-1:
    schema-pattern: "schema_*"
    table-pattern: "table_*"
    expression: "partition id"
    source-column: "id"
    target-column: "id"
    arguments: ["1", "schema_", "table_"]  
複製程式碼
  • mapping-rule-of-instance-1:規則名,使用者指定。由於不同的上游 MySQL 例項需要轉換得到不同的值,因此通常每個 MySQL 例項使用一條專有的規則。

  • schema-pattern / table-pattern:上游庫名、表名匹配模式,與 router-rules 中的對應配置項一致。

  • expression:進行資料轉換的表示式名。目前常用的表示式即為 "partition id",有關該表示式的具體說明見下文。

  • source-column:轉換表示式的輸入資料對應的來源列名,"id" 表示這個表示式將作用於表中名為 id 的列。暫時只支援對單個來源列進行資料轉換。

  • target-column:轉換表示式的輸出資料對應的目標列名,與 source-column 類似。暫時只支援對單個目標列進行資料轉換,且對應的目標列必須已經存在。

  • arguments:轉換表示式所依賴的引數。引數個數與含義依具體表示式而定。

partition id 是目前主要受支援的轉換表示式,其通過為 bigint 型別的值增加二進位制字首來解決來自不同表的資料合併同步後可能產生衝突的問題。partition id 的 arguments 包括 3 個引數,分別為:

  • MySQL 例項 ID:標識資料的來源 MySQL 例項,使用者自由指定。如 "1" 表示匹配該規則的資料來自於 MySQL 例項 1,且這個標識將被轉換成數值後以二進位制的形式作為字首的一部分新增到轉換後的值中。

  • 庫名字首:標識資料的來源邏輯庫。如 "schema_" 應用於 schema_2 邏輯庫時,表示去除字首後剩下的部分(數字 2)將以二進位制的形式作為字首的一部分新增到轉換後的值中。

  • 表名字首:標識資料的來源表。如 "table_" 應用於 table_3 表時,表示去除字首後剩下的部分(數字 3)將以二進位制的形式作為字首的一部分新增到轉換後的值中。

各部分在經過轉換後的數值中的二進位制分佈如下圖所示(各部分預設所佔用的 bits 位數如圖所示):

7.png

假如轉換前的原始資料為 123,且有如上的 arguments 引數設定,則轉換後的值為:

1<<(64-1-4) | 2<<(64-1-4-7) | 3<<(64-1-4-7-8) | 123
複製程式碼

另外,arguments 中的 3 個引數均可設定為空字串(""),即表示該部分不被新增到轉換後的值中,且不佔用額外的 bits。比如將其設定為["1", "", "table_"],則轉換後的值為:

1 << (64-1-4) | 3<< (64-1-4-8) | 123
複製程式碼

有關 column mapping 功能的具體實現,可以閱讀 TiDB-Tools 下的 column-mapping pkg 原始碼

sharding DDL

有了 table router 和 column mapping 功能,DML 的合庫合表資料同步已經可以正常進行了。但如果在增量資料同步的過程中,上游待合併的分表上執行了 DDL 操作,則可能出現問題。我們先來看一個簡化後的在分表上執行 DDL 的例子。

8.png

在上圖的例子中,分表的合庫合表簡化成了上游只有兩個 MySQL 例項,每個例項內只有一個表。假設在開始資料同步時,將兩個分表的表結構 schema 的版本記為 schema V1,將 DDL 執行完成後的表結構 schema 的版本記為 schema V2

現在,假設資料同步過程中,從兩個上游分表收到的 binlog 資料有如下的時序:

  1. 開始同步時,從兩個分表收到的都是 schema V1 的 DML。

  2. 在 t1 時刻,收到例項 1 上分表的 DDL。

  3. 從 t2 時刻開始,從例項 1 收到的是 schema V2 的 DML;但從例項 2 收到的仍是 schema V1 的 DML。

  4. 在 t3 時刻,收到例項 2 上分表的 DDL。

  5. 從 t4 時刻開始,從例項 2 收到的也是 schema V2 的 DML。

假設在資料同步過程中,不對分表的 DDL 進行處理。當將例項 1 的 DDL 同步到下游後,下游的表結構會變更成為 schema V2。但對於例項 2,在 t2 時刻到 t3 時刻這段時間內收到的仍然是 schema V1 的 DML。當嘗試把這些與 schema V1 對應的 DML 同步到下游時,就會由於 DML 與表結構的不一致而發生錯誤,造成資料無法正確同步。

繼續使用上面的例子,來看看我們在 DM 中是如何處理合庫合表過程中的 DDL 同步的。

9.png

在這個例子中,DM-worker-1 用於同步來自 MySQL 例項 1 的資料,DM-worker-2 用於同步來自 MySQL 例項 2 的資料,DM-master 用於協調多個 DM-worker 間的 DDL 同步。從 DM-worker-1 收到 DDL 開始,簡化後的 DDL 同步流程為:

  1. DM-worker-1 在 t1 時刻收到來自 MySQL 例項 1 的 DDL,自身暫停該 DDL 對應任務的 DDL 及 DML 資料同步,並將 DDL 相關資訊傳送給 DM-master。

  2. DM-master 根據 DDL 資訊判斷需要協調該 DDL 的同步,為該 DDL 建立一個鎖,並將 DDL 鎖資訊發回給 DM-worker-1,同時將 DM-worker-1 標記為這個鎖的 owner。

  3. DM-worker-2 繼續進行 DML 的同步,直到在 t3 時刻收到來自 MySQL 例項 2 的 DDL,自身暫停該 DDL 對應任務的資料同步,並將 DDL 相關資訊傳送給 DM-master。

  4. DM-master 根據 DDL 資訊判斷該 DDL 對應的鎖資訊已經存在,直接將對應鎖資訊發回給 DM-worker-2。

  5. DM-master 根據啟動任務時的配置資訊、上游 MySQL 例項分表資訊、部署拓撲資訊等,判斷得知已經收到了需要合表的所有上游分表的該 DDL,請求 DDL 鎖的 owner(DM-worker-1)向下遊同步執行該 DDL。

  6. DM-worker-1 根據 step 2 時收到的 DDL 鎖資訊驗證 DDL 執行請求;向下遊執行 DDL,並將執行結果反饋給 DM-master;若執行 DDL 成功,則自身開始繼續同步後續的(從 t2 時刻對應的 binlog 開始的)DML。

  7. DM-master 收到來自 owner 執行 DDL 成功的響應,請求在等待該 DDL 鎖的所有其他 DM-worker(DM-worker-2)忽略該 DDL,直接繼續同步後續的(從 t4 時刻對應的 binlog 開始的)DML。

根據上面 DM 處理多個 DM-worker 間的 DDL 同步的流程,歸納一下 DM 內處理多個 DM-worker 間 sharding DDL 同步的特點:

  • 根據任務配置與 DM 叢集部署拓撲資訊,在 DM-master 內建立一個需要協調 DDL 同步的邏輯 sharding group,group 中的成員為處理該任務拆解後各子任務的 DM-worker。

  • 各 DM-worker 在從 binlog event 中獲取到 DDL 後,會將 DDL 資訊傳送給 DM-master。

  • DM-master 根據來自 DM-worker 的 DDL 資訊及 sharding group 資訊建立/更新 DDL 鎖。

  • 如果 sharding group 的所有成員都收到了某一條 DDL,則表明上游分表在該 DDL 執行前的 DML 都已經同步完成,可以執行 DDL,並繼續後續的 DML 同步。

  • 上游分表的 DDL 在經過 table router 轉換後,對應需要在下游執行的 DDL 應該一致,因此僅需 DDL 鎖的 owner 執行一次即可,其他 DM-worker 可直接忽略對應的 DDL。

從 DM 處理 DM-worker 間 sharding DDL 同步的特點,可以看出該功能存在以下一些限制:

  • 上游的分表必須以相同的順序執行(table router 轉換後相同的)DDL,比如表 1 先增加列 a 後再增加列 b,而表 2 先增加列 b 後再增加列 a,這種不同順序的 DDL 執行方式是不支援的。

  • 一個邏輯 sharding group 內的所有 DM-worker 對應的上游分表,都應該執行對應的 DDL,比如其中有 DM-worker-2 對應的上游分表未執行 DDL,則其他已執行 DDL 的 DM-worker 都會暫停同步任務,等待 DM-worker-2 收到對應上游的 DDL。

  • 由於已經收到的 DDL 的 DM-worker 會暫停任務以等待其他 DM-worker 收到對應的 DDL,因此資料同步延遲會增加。

  • 增量同步開始時,需要合併的所有上游分表結構必須一致,才能確保來自不同分表的 DML 可以同步到一個確定表結構的下游,也才能確保後續各分表的 DDL 能夠正確匹配與同步。

在上面的示例中,每個 DM-worker 對應的上游 MySQL 例項中只有一個需要進行合併的分表。但在實際場景下,一個 MySQL 例項可能有多個分庫內的多個分表需要進行合併,比如前面介紹 table router 與 column mapping 功能時的例子。當一個 MySQL 例項中有多個分表需要合併時,sharding DDL 的協調同步過程增加了更多的複雜性。

假設同一個 MySQL 例項中有 table_1table_2 兩個分表需要進行合併,如下圖:

10.png

由於資料來自同一個 MySQL 例項,因此所有資料都是從同一個 binlog 流中獲得。在這個例子中,時序如下:

  1. 開始同步時,兩個分表收到的資料都是 schema V1 的 DML。

  2. 在 t1 時刻,收到了 table_1 的 DDL。

  3. 從 t2 時刻到 t3 時刻,收到的資料同時包含 table_1 schema V2 的 DML 及 table_2 schema V1 的 DML。

  4. 在 t3 時刻,收到了 table_2 的 DDL。

  5. 從 t4 時刻開始,兩個分表收到的資料都是 schema V2 的 DML。

假設在資料同步過程中不對 DDL 進行特殊處理,當 table_1 的 DDL 同步到下游、變更下游表結構後,table_2 schema V1 的 DML 將無法正常同步。因此,在單個 DM-worker 內部,我們也構造了與 DM-master 內類似的邏輯 sharding group,但 group 的成員是同一個上游 MySQL 例項的不同分表。

但 DM-worker 內協調處理 sharding group 的同步不能完全與 DM-master 處理時一致,主要原因包括:

  • 當收到 table_1 的 DDL 時,同步不能暫停,需要繼續解析 binlog 才能獲得後續 table_2的 DDL,即需要從 t2 時刻繼續向前解析直到 t3 時刻。

  • 在繼續解析 t2 時刻到 t3 時刻的 binlog 的過程中,table_1schema V2 的 DML 不能向下遊同步;但在 sharding DDL 同步並執行成功後,這些 DML 需要同步到下游。

在 DM 中,簡化後的 DM-worker 內 sharding DDL 同步流程為:

  1. 在 t1 時刻收到 table_1 的 DDL,記錄 DDL 資訊及此時的 binlog 位置點資訊。

  2. 繼續向前解析 t2 時刻到 t3 時刻的 binlog。

  3. 對於屬於 table_1schema V2 DML,忽略;對於屬於 table_2schema V1 DML,正常同步到下游。

  4. 在 t3 時刻收到 table_2 的 DDL,記錄 DDL 資訊及此時的 binlog 位置點資訊。

  5. 根據同步任務配置資訊、上游庫表資訊等,判斷該 MySQL 例項上所有分表的 DDL 都已經收到;將 DDL 同步到下游執行、變更下游表結構。

  6. 設定新的 binlog 流的解析起始位置點為 step 1 時儲存的位置點。

  7. 重新開始解析從 t2 時刻到 t3 時刻的 binlog。

  8. 對於屬於 table_1schema V2 DML,正常同步到下游;對於屬於 table_2shema V1 DML,忽略。

  9. 解析到達 step 4 時儲存的 binlog 位置點,可得知在 step 3 時被忽略的所有 DML 都已經重新同步到下游。

  10. 繼續從 t4 時刻對應的 binlog 位置點正常同步。

從上面的分析可以知道,DM 在處理 sharding DDL 同步時,主要通過兩級 sharding group 來進行協調控制,簡化的流程為:

  1. 各 DM-worker 獨立地協調對應上游 MySQL 例項內多個分表組成的 sharding group 的 DDL 同步。

  2. 當 DM-worker 內所有分表的 DDL 都收到時,向 DM-master 傳送 DDL 相關資訊。

  3. DM-master 根據 DM-worker 發來的 DDL 資訊,協調由各 DM-worker 組成的 sharing group 的 DDL 同步。

  4. 當 DM-master 收到所有 DM-worker 的 DDL 資訊時,請求 DDL lock 的 owner(某個 DM-worker)執行 DDL。

  5. owner 執行 DDL,並將結果反饋給 DM-master;自身開始重新同步在內部協調 DDL 同步過程中被忽略的 DML。

  6. 當 DM-master 發現 owner 執行 DDL 成功後,請求其他所有 DM-worker 開始繼續同步。

  7. 其他所有 DM-worker 各自開始重新同步在內部協調 DDL 同步過程中被忽略的 DML。

  8. 所有 DM-worker 在重新同步完成被忽略的 DML 後,繼續正常同步。

資料同步過濾

在進行資料同步的過程中,有時可能並不需要將上游所有的資料都同步到下游,這時一般期望能在同步過程中根據某些規則,過濾掉部分不期望同步的資料。在 DM 中,支援 2 種不同級別的同步過濾方式。

庫表黑白名單

DM 在 dumper、loader、syncer 三個處理單元中都支援配置規則只同步/不同步部分庫或表。

對於 dumper 單元,其實際呼叫 mydumper 來 dump 上游 MySQL 的資料。比如只期望匯出 test 庫中的 t1、t2 兩個表的資料,則可以為 dumper 單元配置如下規則:

name-of-dump-rule:
    extra-args: "-B test -T t1,t2"
複製程式碼
  • name-of-dump-rule:規則名,使用者指定。當有多個上游例項需要使用相同的規則時,可以只定義一條規則,多個不同的例項通過規則名進行引用。

  • extra-args:dumper 單元額外引數。除 dumper 單元中明確定義的配置項外的其他所有 mydumper 配置項都通過此引數傳入,格式與使用 mydumper 時一致。

有關 mydumper 對庫表黑白名單的支援,可檢視 mydumper 的引數及 mydumper 的原始碼

對於 loader 和 syncer 單元,其對應的庫表黑白名單規則為 black-white-list。假設只期望同步 test 庫中的 t1、t2 兩個表的資料,則可配置如下規則:

name-of-bwl-rule:
    do-tables:
    - db-name: "test"
      tbl-name: "t1"
    - db-name: "test"
      tbl-name: "t2"
複製程式碼

示例中只使用了該規則的部分配置項,完整的配置項及各配置項的含義,可閱讀該功能對應的使用者文件。DM 中該規則與 MySQL 的主從同步過濾規則類似,因此也可參考 Evaluation of Database-Level Replication and Binary Logging OptionsEvaluation of Table-Level Replication Options

對於 loader 單元,在解析 SQL 檔名獲得庫名錶名後,會與配置的黑白名單規則進行匹配,如果匹配結果為不需要同步,則會忽略對應的整個 SQL 檔案。對於 syncer 單元,在解析 binlog 獲得庫名錶名後,會與配置的黑白名單規則進行匹配,如果匹配結果為不需要同步,則會忽略對應的(部分)binlog event 資料。

binlog event 過濾

在進行增量資料同步時,有時會期望過濾掉某些特定型別的 binlog event,兩個典型的場景包括:

  • 上游執行 TRUNCATE TABLE 時不希望清空下游表中的資料。

  • 上游分表上執行 DROP TABLE 時不希望 DROP 下游合併後的表。

在 DM 中支援根據 binlog event 的型別進行過濾,對於需要過濾 TRUNCATE TABLEDROP TABLE 的場景,可配置規則如下:

name-of-filter-rule:
​    schema-pattern: "test_*"
​    table-pattern: "t_*"
​    events: ["truncate table", "drop table"]
​    action: Ignore
複製程式碼

規則的匹配模式與 table router、column mapping 類似,具體的配置項可閱讀該功能對應的使用者文件。

在實現上,當解析 binlog event 獲得庫名、表名及 binlog event 型別後,與配置的規則進行匹配,並在匹配後依據 action 配置項來決定是否需要進行過濾。有關 binlog event 過濾功能的具體實現,可以閱讀 TiDB-Tools 下的 binlog-filter pkg 原始碼

TiDB Ecosystem Tools 原理解讀系列(三)TiDB-DM 架構設計與實現原理

相關文章