『壹』 技術分享 | 兩個單機 MySQL 該如何校驗數據一致性
業務有兩個 MySQL 集群是通過 MQ 進行同步的,昨晚 MQ 出現異常,報了很多主鍵沖突,想請 dba 幫忙校驗一下兩個集群的數據是否一致。
當接到這個需求的時候並沒當回事,隱約有點印象 pt-table-checksum 能通過 dsn 實現 MySQL 的數據校驗,所以當時就應承下來了。不曾想,啪啪打臉,回想起來真是草率了。
本文參考的是 pt-table-checksum 的校驗邏輯,基於數據塊去遍歷每個表,然後比對 checksum 的值判斷該塊是否一致,本文主要是想聊聊我在實現數據校驗腳本過程中遇到的問題以及解決思路,希望對大家有幫助。
利用線上的配置文件搭建一套主從環境。
這個用例將通過 dsn 方式連接從庫。
這個用例將通過 dsn 方式連接從庫,但是會將從庫的復制鏈路 stop 掉,並清空復制信息。
熟悉 pt-table-checksum 的朋友應該都知道,該工具是基於主鍵(非空唯一鍵)進行掃描數據行,其實這個邏輯針對整型單列主鍵實現起來很簡單,但是如果是聯合主鍵且是字元型,好像就沒那麼簡單了,有興趣的可以思考一下。下面我先說一下大致的邏輯:
第一步:判斷 _min_rowid 是否為空,為空就取該表的第一行,並記作 _min_rowid 。
第二步:根據 _min_rowid 作為條件進行掃描該表,取下一個數據塊的數據,記錄數據塊的最後一行數據的主鍵值,記錄 checksum 的值,並記下 _min_rowid 。
第三步:判斷_min_rowid是否為空,非空重復第二步,為空退出檢查。
通過上述三個步驟可以看到,如果是單列整型的主鍵,實現起來很簡單,但是問題來了,業務的表的主鍵五花八門,有的是聯合主鍵,有的是字元型的聯合主鍵,還有整型+字元型的聯合主鍵,那麼上述的實現方式顯然是有問題的。所以實現起來需要多考慮幾個問題:
鑒於存在上述兩個問題,可以參考如下實現邏輯:
假如有這么一個聯合主鍵欄位 primary key(a,b,c) 都是整型,該如何編寫遍歷 sql 呢?起初我的想法很簡單,具體如下:
至此在編寫校驗腳本過程遇到的兩個問題就算告一段落了,剩下的就是各種邏輯處理了,不過多贅述,有興趣的可以自行閱讀腳本文件。
本著最低程度影響業務,所以取消加鎖邏輯。但是又要保證該數據塊的數據一致性,如果這個數據塊是個熱數據,當前正在變更,那麼校驗的時候難免會不一致。所以只能通過多次校驗實現,默認是校驗20次,其中有一次校驗結果是一致,就認為是一致的,如果前5次校驗過程中,這個數據塊的數據沒有變化,也視為不一致(可能是因為延遲,也可能是真的不一致)。
pt-table-checksum 不校驗表結構,改寫時添加表結構的校驗。
可以基於表的並行校驗,可由用戶指定並行數,但是腳本有個安全機制,如果用戶指定的並行數大於當前 cpu 空閑核心數,就會按當前(空閑核心數-1)作為並行數。
添加網路監控,由用戶指定網路上限百分比,當網卡流量超過這個百分比就暫停任務,等待網卡流量低於閾值才會繼續任務。這個主要是出於對於中間件(mycat)的場景或者分布式資料庫(tidb)的場景。
支持定時任務功能,用戶可以使用這個功能規避業務高峰,僅在業務低峰進行數據校驗。
不僅限於主從節點的校驗,只要目標對象支持 MySQL 的標准 SQL 語法就能做數據校驗。
校驗邏輯是通過 SQL 採集目標節點的資料庫,如果目標資料庫系統當前存在異常,無疑是雪上加霜,將會觸發未知問題,所以添加超時機制,單次取數據塊的閾值是5s,超過5秒就放棄等待重試。測試發現,有時候即便觸發超時了,但是 SQL 任務還是會在目標資料庫的 processlist 中能看到,所以又添加了一個 kill 機制,超時後會觸發一個 kill processlist id 的動作。另外為了避免 kill 錯,在每個 SQL 對象添加了一個32位的 md5 值,每次 kill 的時候會校驗這個 md5 值。
本工具借鑒 pt-table-checksum 工具思路改寫,可以檢查隨意兩個 mysql(支持 mysql sql 語法的資料庫)節點的數據一致性。
基於主鍵以一個塊遍歷數據表,比對checksum的值,塊的大小可通過參數指定。 (1)獲取該表的第一個數據塊的查詢SQL。 (2)將兩個目標節點的數據塊的checksum的值,記錄到臨時文件,file1 file2。 (3)比對file1 file2是否一致。
第一步:先開啟一個 screen 監控網路
第二步:新開啟一個screen執行校驗任務
(1)info.log 文件
(2)list目錄
(3)md5 目錄
(4)pri 目錄
(5)res 目錄
這是 table 目錄下記錄某個數據塊不一致的一個例子
這是 diff 目錄下記錄某個數據行不一致的一個例子
(6)skip.log 文件
本工具是參考了 pt-table-checksum 工具的一些思路並結合自身經驗進行改寫,尚有很多不足之處,僅做學習交流之用, 如有線上環境使用需求,請在測試環境充分測試。