1. 程式人生 > >gh-ost原理

gh-ost原理

osc select 累加 退出程序 ren roc 結合 use 集群

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原理