摘要:簡介項目地址主從環境下數據一致性校驗經常會用工具,它的原理及實施過程之前寫過一篇文章生產環境使用檢查數據一致性。上面的配置文件可以認為是用于控制程序的,這個配置文件是指定要校驗的源庫和目標庫信息,以及要檢驗哪些表。
1. 簡介
項目地址:https://github.com/seanlook/p...
主從環境下數據一致性校驗經常會用 pt-table-checksum 工具,它的原理及實施過程之前寫過一篇文章:生產環境使用 pt-table-checksum 檢查MySQL數據一致性。但是DBA工作中還會有些針對兩個表檢查是否一致,而這兩個表之間并沒有主從關系,pt工具是基于binlog把在主庫進行的檢查動作,在從庫重放一遍,此時就不適用了。
總會有這樣特殊的需求,比如從阿里云RDS實例遷移到自建mysql實例,它的數據傳輸服務實現方式是基于表的批量數據提取,加上binlog訂閱,但強制row模式會導致pt-table-checksum沒有權限把會話臨時改成statement。另一種需求是,整庫進行字符集轉換:庫表定義都是utf8,但應用連接使用了默認的 latin1,要將連接字符集和表字符集統一起來,只能以latin1導出數據,再以utf8導入,這種情況數據一致性校驗,且不說binlog解析程序不支持statement(如canal),新舊庫本身內容不同,pt-table-checksum 算出的校驗值也會不一樣,失效。
所以才萌生了參考 pt-table-checksum 自己寫了一個:px-table-checksum 。
2. 實現方法整體思路是借鑒pt-table-checksum,從源庫批量(即chunk)取出一塊數據如1000行,計算CRC32值,同樣的語句在目標庫運行一遍,結果都存入另一個庫,最后檢查對應編號的chunk crc值是否一致。知道不一致還不行,得能否快速方便的修復差異,所以繼續根據那些不一致的chunk,去目標庫和源庫找到不一致的行,是缺失,還是多余,還是被修改了,然后生成修復sql,根據指示是否自動修復。
那么問題就在于:
如何確定批次,也就是下一個chunk該怎么???
我還沒想做到pt-table-checksum那樣,可以根據負載動態調整chunk大小,甚至活躍線程數超過閥值就暫停檢查,上來工作量就太大了。目前每次計算的chunk的行數是固定的,可以配置1000或2000等。
所以就要用到分頁查詢,根據(自增或聯合)主鍵、唯一索引,每次limit 1000后升序取最后一條,作為下一批的起始。所以要分析表上的鍵情況,組合查詢條件。目前僅能檢查有主鍵或唯一所以的表。
如何保證源庫和目標庫,運行的sql一樣?
之前一版是目標庫和源庫,以多線程各自計算chunk,入庫,后來才意識到嚴重的bug:比如同樣是取1000行,如果目標庫少數據,那么下一個chunk起始就不一樣,比較的結果簡直一塌糊涂。
所以必須保證相同編號的chunk,起點必須相同,所以想到用隊列,存放在源庫跑過的所有校驗sql,模擬pt工具在目標庫重放??紤]到要多線程同時比較多個表,隊列可能吃內存過大,于是使用了redis隊列。
直接在數據庫中計算crc32,還是取出數據在內存里計算?
翻了pt-table-checksum的源碼,它是在數據庫里計算的。但是第一節里說過,如果目標庫和源庫要使用不同的字符集才能讀出正確的數據,只能查詢出來之后再比較。所以 px-table-checksum 兩種都支持,只需指定一個配置項。
同時檢查多個表,源庫sql擠在隊列,目標庫拿出來執行時過了1s,此時源庫那條數據又被修改了一次同步到了目標庫,會導致計算結果不一致,實則一致,怎么處理
無法處理,是px-table-checksum相比pt-table-checksum最大的缺陷。
但為了盡可能減少此類問題(比如主從延遲也可能會),特意設計了多個redis隊列,目標庫多個檢查線程,即比如同時指定檢查8個表,源庫檢查會有8個線程對應,但可以根據表的寫入情況,配置4個redis隊列(目前是隨機入列),10個目標庫檢查線程,來減少不準確因素。
但站在我的角度往往來說,不一致的數據會被記錄下來,如果不多,人工核對一下;如果較多,就再跑一遍檢查,如果兩次都有同一條數據不一致,那就有情況了。
如果檢查期間源表數據,變化頻繁,有可能檢查的結果不準確
也就是上面第4點的問題。很明顯,這個程序每個檢查的事務是分開的,不像pt工具能嚴格保證每條檢查sql的事務順序。但有不一致的數據再排查一下就ok了。實際在我線上使用過程中,99.9%是準確的。
表上必須有主鍵或唯一索引
程序會檢查,如果沒有會退出。
varbinay,blob等二進制字段不支持修復
其實也不是完全不支持,要看怎么用的。開發如果有把字符先轉成字節,再存入mysql,這種就不支持修復。是有辦法可以處理,那就是從源庫查時用 hex()函數,修復sql里面unhex()寫回去。
該python程序基于2.7開發,2.6、3.x上沒有測試。使用前需要安裝 MySQLdb和hotqueue:
$ sudo pip install MySQL-python hotqueue
要比較的表和選項,使用全配置化,即不通過命令行的方式指定(原諒命令行參數使用方式會額外增加代碼量)。
4.1 px-table-checksum.py主程序,運行python px-table-checksum.py 執行一致性檢查,但一定了解下面的配置文件選項。
4.2 settings_checksum.py配置選項
CHUNK_SIZE: 每次提取的chunk行數
REDIS_INFO: 指定使用redis隊列地址
REDIS_QUEUE_CNT: redis隊列數量,消費者(目標庫)有一一對應的線程守著隊列
REDIS_POOL_CNT: 生產者(源庫)redis客戶端連接池。這個設計是為了緩解GIL帶來的問題,把入列端與出列端分開,因為如果表多可能短時間有大量sql入隊列,避免hotqueue爭用
CALC_CRC32_DB: True 表示在db里面計算checksum值,False表示取出chunk數據在python里面計算。默認給的值是根據連接字符集定的。
DO_COMPARE: 運行模式
0: 只提取數據計算,不比較是否一致??梢栽谥笤谀J?下只比較
1: 計算,并比較。常用,每次計算之前會刪除上一次這個待檢查表的結果,比較的結果只告訴哪些chunk號不一致。
2: 不計算,只從t_checkum結果比較。常用,計算是消耗數據庫資源的,可以只對已有的checksum計算結果比較不一致的地方。類似pt工具的--replicate-check-only選項。
GEN_DATAFIX:
與DO_COMPARE結合使用,為 True 表示對不一致的chunk找到具體不一致行,并生成修復sql;為 False 則什么都不做。
RUN_DATAFIX:
與GEN_DATAFIX結合使用,為 True 表示對生成的修復sql,在目標庫執行。需要謹慎,如果哪一次設置了修復,記得完成后改回False,不然下次檢查另一個表就出意外了,所以特意對這個選項再加了一個確認提示。
DB_CHECKSUM: 一個字典,指定checksum的結果存到哪里
配置文件有示例,必須指定 db_name,表會自動創建。
上面的配置文件可以認為是用于控制程序的,這個配置文件是指定要校驗的源庫和目標庫信息,以及要檢驗哪些表。
TABLES_CHECK: 字典,指定要檢查哪些表的一致性,db名為key,多個table名組成列表為value。暫不支持對整個db做檢查,同時比較的表數量不建議超過8個
DB_SOURCE: 字典,指定源庫的連接信息
DB_SOURCE: 字典,指定目標庫的連接信息
原文鏈接地址:http://seanlook.com/2016/11/2...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44276.html
摘要:通過對一些客戶的跨云遷移過程進行總結,發現普遍存在的挑戰有三點數據完整性和一致性挑戰。簡而言之,跨云遷移過程中的數據一致性主要就集中在存量數據的遷移如何保證一致。前言隨著互聯網業務發展對容災以及對訪問加速、多供應商成本控制等需求的產生,互聯網公司的多云部署和跨云遷移逐漸成為剛需,而在此過程中,最困擾運維和研發人員的就是數據的遷移和同步。俗語說 上屋搬下屋,搬灑一籮谷 ,在業務的遷移過程中一旦...
閱讀 1762·2021-10-12 10:12
閱讀 2530·2021-09-29 09:42
閱讀 2711·2021-09-03 10:28
閱讀 2249·2019-08-30 15:54
閱讀 1153·2019-08-30 15:53
閱讀 1388·2019-08-30 11:26
閱讀 3357·2019-08-30 11:02
閱讀 2134·2019-08-30 11:02