MySQL復制 -- 復制出錯怎么辦?
假如我們生產環境復制出錯?該怎么辦呢?
下面提供幾種辦法:
1. 手工處理,補回不一致數據(可以利用主庫來補數據、也可以利用binlog來補數據)
2.用開源工具來解決一致性問題
3.自己造輪子,解決一致性問題
至于如何通過手工方式來修復不一致數據,我就不一一說了,大概就是缺啥補撒把,要是大量的不一致,那么手工來搞必然會累的半死,而且也不科學,本文主要介紹一下三方工具pt-table-sync
Pt-table-sync 原理:
1. 在主庫上分析表結構,把說有字段轉換成varchar類型
2. 根據表上的索引,把表數據分成一個個的chunck
3. 對于每個 chunck ,把字段利用 concat_ws() 函數鏈接到一起,然后對這個值計算 MD 5 值,存到統計表(test庫下邊)
4. 由于復制關系,這個統計數據會被復制到從庫,并且同樣的語句也會被執行一遍
5. 到此基本的條件都具備了, 那么就開始執行對比了,具體對比過程是這樣的:對于每個chunck會有個 主庫的MD 5 值和備考的MD 5 值,for 每個chunck,if MD 5 值相等,則跳過;else 深入chunck ,逐行檢查每行數據;
問題來了
1. 那么由于時主從關系,復制必然有延遲的情況,如何保證在檢查md 5 時 主從數據是一致的呢,或者說是相同數量的行呢?
這個就的深入到 p t-table-sync 在計算chunck MD 5 值的時候是如何計算的了:
主庫上: 對每一個 chunk ,在校驗時加上 for update 鎖。一旦獲得鎖,就記錄下當前主庫的 show master status 值。
從庫上 : 執行 select master_pos_wait() 函數,等待從庫 sql 線程執行到 show master status 得到的位置。以此保證,主從上關于這個 chunk 的內容均不再改變。
2. 主備不一致時候,是怎么修復的呢?
對于主庫有但是備庫不存在的數據(或者主備不一致):那么備庫會跳過,在主庫上執行 replace into 操作,通過binlog復制的方式在備庫進行重新應用。
對于備庫有, 但主庫不存在的數據:那么依然是在主庫執行 delete 操作(主庫本來就不存在數據, 所以這個語句對于主庫來說是安全的)
關于這個的思考:
1.這是一種 盲目的復制同步檢查機制 ,同樣的數據會在主庫和備考計算,給主庫備庫都帶來了額外的負擔,同時由于復制關系,這個數據會被copy到從庫,給網絡帶來了壓力,給備庫也帶來了壓力(一個是在應用主庫傳過來的數據的時候,另一個是在計算md 5 值時)
2. 由于我們的 replace into機制,那么就必須要求這個表上存在 主鍵或者唯一健
3. 由于在檢查 chunck 的時候采用 s elect for update 那么必然會加 X 鎖,如果備庫延遲太大,則應用的性能會有所下降
那么我們有沒有一種不盲目的方式呢?其實我們可以自己實現的,具體如何實現,我將在稍后講到
</div> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>