gh-ost原理
gh-ost原理
一、三種模式架構圖
1、連上從庫,在主庫上修改
這是gh-ost默認的工作模式,它會查看從庫情況,找到集群的主庫並且連接上去,對主庫侵入最少,大體步驟是:
在主庫上創建_xxx_gho、_xxx_ghc,並修改_xxx_gho表結構;
從slave上讀取二進制日誌事件,將變更應用到主庫上的_xxx_gho表;
在主庫上讀源表的數據寫入_xxx_gho表中:insert into igore....select;
在主庫上完成表切換;
2、直接主庫修改
在主庫上創建_xxx_gho、_xxx_ghc,並修改_xxx_gho表結構; 從主庫上讀取二進制日誌事件,將變更應用到主庫上的_xxx_gho表; 在主庫上讀源表的數據寫入_xxx_gho表中:insert into igore....select; 在主庫上完成表切換;
3、在從庫上修改和測試
這種模式會在從庫上做修改。gh-ost仍然會連上主庫,但所有操作都是在從庫上做的,不會對主庫產生任何影響。在操作過程中,gh-ost也會不時地暫停,以便從庫的數據可以保持最新。
--migrate-on-replica選項讓gh-ost直接在從庫上修改表。最終的切換過程也是在從庫正常復制的狀態下完成的。
--test-on-replica表明操作只是為了測試目的。在進行最終的切換操作之前,復制會被停止。原始表和臨時表會相互切換,再切換回來,最終相當於原始表沒被動過。主從復制暫停的狀態下,你可以檢查和對比這兩張表中的數據。
二、原理
1、檢查校驗環境
測試db是否可連通,並且驗證database是否存在 確認連接實例是否正確 權限驗證 show grants for current_user() binlog驗證,包括row格式驗證和修改binlog格式後的重啟replicate 原表存儲引擎,外鍵,觸發器檢查,行數預估等
2、創建binlog streamer連接到主庫或者從庫,添加binlog的監聽
3、創建log表_xxx_ghc和ghost表_xxx_gho並修改ghost表結構到最新
4、開始遷移數據:row copy和binlog apply同時進行
1)最小值:select `id` from darren`.`t4` order by id` asc limit 1; 2) 最大值:select `id` from darren`.`t4` order by id` desc limit 1; 3) 計算第一個chunk: select `id` from `darren`.`t4` where `id` >= _binary‘1‘ and `id` <= _binary‘58594‘ order by `id` asc limit 1 offset 999 最後一個chunk如果不足1000,那麽上面sql查詢為空,這時運行: select `id` from ( select `id` from `darren`.`t4` where `id` > _binary‘58000‘ and `id` <= _binary‘58594‘ order by `id` asc limit 1000 ) select_osc_chunk order by `id` desc limit 1; 4)循環插入數據:insert ignore into `darren`.`_t4_gho` (`id`, `name`, `c1`) (select `id`, `name`, `c1` from `darren`.`t4` force index (`PRIMARY`) where `id` >= _binary‘1‘ and `id` <= _binary‘1000‘ lock in share mode )
4.1、rowcopy數據和應用binlog順序不同是否產生數據沖突
數據遷移過程中sql映射關系:
rowcopy和binlog應用各種排列組合:
數據遷移過程,涉及三個操作:A:對原表進行rowcopy;B:應用程序的DML;C:應用binlog到新表,因為DML操作才會記錄binglog,所以C操作一定在B操作的後面,共有如下幾種組合:
1.insert 操作
binlog是最權威的,gh-ost的原則是以binlog優先,所以無論任何順序下,數據都是和binlog保持一致,如果rowcopy在後,會insert ignore,如果binlog apply在後會replace into掉。
2.update/delete 操作
對已經rowcopy過的數據,出現對原表的update/delete操作。這時候會全部通過binlog apply執行,註意binlog apply的update是對某一條記錄的全部列覆蓋更新,所以不會有累加的問題。
對尚未遷移的數據,出現對原表的update/delete操作。這時候對新表的binlog apply會是空操作,具體數據由rowcopy遷移。
特殊情況下:
先對原表更新完以後,rowcopy在binlog apply之前把數據遷移了過去,而在binlog event過來以後,會再次應用,這裏有問題?其實結合gh-ost的binlog apply之前把數據遷移了過去,
而在binlog的sql映射規則,insert操作會被replace重新替換掉,update 會更新對應記錄全部行,delete 會是空操作。最終數據還是一致的狀態。
4.2、binlog同步數據何時結束?
copy完數據向_xxx_ghc寫入status:AllEventsUpToLockProcessed:1533533052229905040,當binlogsyncer過濾到該值表示所有event都已應用
5、copy完成後進行原子性cut-over階段
5.1) C10:
創建magic表_xxx_del,目的為了防止過快的進行rename操作和意外情況rename
對源表和magic表_xxx_del加write鎖
5.2) C11...C19: 新的請求進來,關於原表的請求被blocked
5.3) C20: 執行:rename table `t4` to `_t4_del`,`_t4_gho` to `t4`;這時被阻塞,timeout:3s。(這一步只有binlog event應用完成後)
5.4) 檢查是否有blocked 的RENAME請求,通過show processlist
5.5) C10:
刪除magic表(只有show processlist裏存在被block的rename才進行)
釋放瑣
不同階段失敗後如何處理:
如果5.1失敗,退出程序,比如建表成功,加鎖失敗,退出程序,未加鎖
rename請求來的時候,會話C10死掉,lock會自動釋放,同時因為_xxx_del的存在rename也會失敗,所有請求恢復正常
rename被blocked的時候,會話C10死掉,lock會自動釋放,同樣因為_xxx_del的存在,rename會失敗,所有請求恢復正常
C20死掉,gh-ost會捕獲不到rename,會話C10繼續運行,釋放lock,所有請求恢復正常
6、清理戰場
7.1) 關閉binlogsyncer連接
7.2) 刪除源表和_t4_ghc表
gh-ost原理