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表