多種方式告訴你如何計算DM同步資料到TiDB的延時時間

balahoho發表於2022-02-09

背景

使用者在做技術選型的過程中,總是會對一些資料指標比較關心,特別是在和競品相比較的時候,更加需要一些有說服力的資料。基於MySQL開發的專案在遷移到TiDB的時候,使用DM同步資料是必不可少的一個環節,我在最近的一次POC中就碰到了這樣一個需求,需要評估一個具體的延時時間參考值,因為使用者在遷移前期的過渡階段是把TiDB作為MySQL的從庫,有些場景對這個延時很敏感,如果延時太大會直接影響業務。

由於DM並不能直接看到整個鏈路的延時時間,所以我們必須另闢蹊徑找一些辦法來實現,以下是我實踐過的幾種辦法,也希望能拋磚引玉,帶出其他大佬給社群帶來更好的方案。

我的思路比較簡單,就是分別根據上下游事務的某個時間點來計算時間差,這個時間差應該要精確到毫秒級,可以從三個方向入手:

  • Binlog Position

  • TiDB General log

  • SQL自動記錄時間

接下來就分別看一下如何實現。

基於Binlog Position

DM增量同步是基於訂閱MySQL Binlog來實現的,所以首先考慮的辦法就是通過Binlog Position來定位某一個事務,只要分別找到同一個Position在Binlog和DM-Worker Log中記錄的時間,就可以大致計算出這個時間差。

我使用如下一張測試表來演示這個過程:

CREATE TABLE `table1` (
  `id` int(11) NOT NULL,
  `mysql_created` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

在DM Task完全啟動成功之後,我們往MySQL裡的table1插入一條資料:

insert into table1 values(1,null);

插入成功後我們找到這個事務第一個events的position,這個示例中是1422:

接下來去binlog檔案中解析出這段範圍內的事務內容,裡面有我們需要的時間:

注意看裡面的TIMESTAMP內容,意思是事務開始時的時間是21:45:38:572,原始內容精確到了微秒級別,我們這裡只取毫秒來計算。

然後拿事務開始的position去dm-worker的日誌中搜尋相應的內容,當binlog被處理完成後會輸出flushed checkpoint字樣的內容,我們根據關鍵字去日誌檔案中搜尋:

從這裡可以得到1422被寫入完成的時間是21:45:38.603,前後相減一下大概時間差是31ms。

要注意的是,我理解整個鏈路的過程應該是:mysql(事務開始)->binlog->dm-worker->tidb->dm-worker,相當於TiDB寫完後多了一個通知dm-worker的過程。

基於TiDB General log

第二種與前一種類似,我希望能定位到事務實際被TiDB執行完成的時間,這時候可以藉助TiDB的GENERAL_LOG功能,用事務號(TSO)去定位。

我們首先開啟TiDB例項的General Log開關:

mysql> set tidb_general_log=1;
Query OK, 0 rows affected (0.08 sec)

前半部分和之前一樣,還是去binlog檔案中找到MySQL事務開始時間戳,這裡是22:08:55:419

然後開啟TiBD的Dashboard頁面,用如下關鍵字搜尋TiDB節點的日誌:

雖然這個頁面能看到日誌的記錄時間,但是存在兩個問題,一個是不能精確到毫秒,第二個這並不是事務的提交時間,我們需要進一步根據事務號(TSO)去原始檔案中搜尋準確時間。

這裡的commit時間是22:08:55.434,前後相減的時間差大概15ms。

這裡也可以一步到位直接去原始log檔案去搜,省去Dashboard查詢TSO的過程。

這個鏈路過程是:mysql(事務開始)->binlog->dm-worker->tidb(事務提交)。

基於SQL自動記錄時間

前面兩種方法都要各種搜尋日誌稍微有點麻煩,本著將偷懶進行到底的精神,能不能直觀地看出上下游各自的時間?最理想的情況是:一句SQL就能查出來。

從前面的測試中可以發現,時間欄位設定當前時間為預設值只對上游生效,同步到TiDB的時候是把實際值傳過去了,並不是根據欄位定義生成新值。因此,我希望資料到TiBD的時候也能生成當前時間寫入某個欄位,但是這個欄位不能在MySQL中存在,也就是說上下游資料結構不一樣。

那DM可以支援這種同步嗎?必然是可以的。

關於上下游異構同步官網文件有詳細介紹,大家可以參考文件:https://docs.pingcap.com/zh/tidb-data-migration/stable/manage-schema。
我們要使用的帶預設值異構同步其實更簡單,DM不用做任何操作就能支援。

我們在前面的DM Task完全不動的情況下,只給下游TiDB的table1增加一個欄位

alter table table1 add COLUMN tidb_created timestamp(3) NOT NULL  DEFAULT current_timestamp(3);

然後往上游插入一條測試資料:

insert into table1 values(3,null);

插入成功後去TiDB中查詢這個表,兩個建立時間都能看到了:

是不是非常簡單。

這個鏈路的過程是:mysql(事務開始)->binlog->dm-worker->tidb(事務開始)。

總結

以上3種方式從不同維度計算了一次資料同步的延時情況,這個資料具有一定的參考性。但是使用的過程中要注意每一種的區別,選擇你最適合最關心的指標來作為參考。

本文如有不正確的地方歡迎指出,當然了,也歡迎大家推薦更好的方案,一起交流~

相關文章