[翻译]Triggerless design.md
源文將持續(xù)更新,請點擊此處閱讀原文
介紹gh-ost不使用Trigger背后的邏輯和算法,其次是這樣設(shè)計的含義,優(yōu)點,以及缺點。
基于觸發(fā)器遷移的理念
這里有兩個比較流行的online DDL工具:
pt-online-schema-change
Facebook OSC
前者使用同步設(shè)計原理:它在原表上創(chuàng)建三個觸發(fā)器(AFTER INSERT,AFTER UPDATE,AFTER DELETE)。每個觸發(fā)器將原表上的操作重播到ghost表中。因此,原表上的每一個UPDATE都會被重播到gh-ost表中,INSERT/DELETE也是如此。觸發(fā)器和原表的操作存在與同一個事務(wù)空間里。
后者使用異步設(shè)計原理:它在原表上創(chuàng)建三個觸發(fā)器(AFTER INSERT,AFTER UPDATE,AFTER DELETE)。它也會創(chuàng)建一個changelog表。觸發(fā)器不會直接將原表操作重播到ghost表中。取而代之的是,它會在changelog中添加一條記錄。原表上的UPDATE操作在changelog表中插入一條記錄像"原表上有一個UPDATE操作,將這個值變?yōu)榱肆硗庖粋€值",INSERT/DELETE也是如此。一個后臺的線程會實時去查看changelog表的變化,并應(yīng)用所有的變更應(yīng)用到ghost表上。這是一個異步的操作,因為gh-ost重播操作的過程與原表的操作不在相同的事務(wù)空間中了,并且gh-ost的重播操作可能會延遲。值得注意的是,changelog的記錄寫入操作還是與原表操作存在于相同的事務(wù)空間中。
不基于觸發(fā)器的異步遷移理念
gh-os使用不基于觸發(fā)器的異步遷移方案。但是它不需要觸發(fā)器,因為它不像FB工具那樣需要一個changelog表。因為它不是基于changelog表做數(shù)據(jù)遷移,而是基于MySQL二進(jìn)制日志(binlog)。
gh-ost基于binlog_format=row(RBR)獲取來源于原表的記錄,你也可以基于binlog_format=statement(SBR)獲取記錄,詳情請點擊。
RBR格式的二進(jìn)制日志將復(fù)雜的SQL語句(可能存在多表)分解為不同的單表單行記錄,這樣更易于將binlog應(yīng)用到gh-ost上。
gh-ost將自己偽裝成MySQL從庫:gh-ost連上主庫,并且從主庫獲取binlog。因此,它獲取binlog日志,并且通過過濾得到原表的操作事件。
gh-ost可以直接連接到主庫上,但是gh-ost更喜歡連接到一個從庫上。但是該從庫需要設(shè)置參數(shù)log_slave_updates=1和binlog_format=row(binlog_format也可以通過調(diào)整gh-ost參數(shù)來進(jìn)行自動設(shè)置)。
讀取二進(jìn)制日志,特別是在在從庫上讀取二進(jìn)制,進(jìn)一步強(qiáng)調(diào)了算法的異步性。當(dāng)有一個事物寫入到了binlog中,它依舊需要等gh-ost偽裝成一個從庫之后,才開始獲取binlog并且應(yīng)用到gh-ost中。
異步設(shè)計也意味著有很多值得注意的因素,稍后將做討論。
工作流程概覽
整個工作流程包括:原表上讀取表數(shù)據(jù),binlog讀取操作事件,檢查主從延遲以及其它的節(jié)流參數(shù),將變更應(yīng)用到ghost表中(通常是master上的ghost表),通過二進(jìn)制日志流發(fā)送提示等等。
工作流程如下:
初始化設(shè)置&驗證
初始化設(shè)置不是一個并發(fā)操作。
連接從庫(推薦)/主庫,檢查主庫標(biāo)志
預(yù)驗證ALTER語句
初始化驗證:權(quán)限以及表是否存在
創(chuàng)建changelog和ghost表
在ghost表上執(zhí)行ALTER語句
對比原表和ghost表的結(jié)構(gòu),檢查共享列,共享唯一鍵,驗證是否有外鍵,選擇共享的唯一鍵,這個鍵用于處理表的唯一標(biāo)識,比如數(shù)據(jù)遷移等
開始監(jiān)聽binlog,監(jiān)聽changelog表的事件
在changelog表上注入"good to go"的記錄(被二進(jìn)制日志攔截)
開始監(jiān)聽原表DML的binlog事件
獲取之前原表和ghost表的共享唯一鍵在原表上的最小值和最大值
數(shù)據(jù)復(fù)制流程
該步驟包括多個移動部分,所有操作相互協(xié)調(diào)并發(fā)執(zhí)行。
設(shè)置一個心跳機(jī)制:頻繁的寫入到changelog表(這是一個低負(fù)載的操作)
心跳機(jī)制不斷的更新狀態(tài)
定期(頻繁)檢查潛在的節(jié)流信息或者提示
在原表上通過行范圍控制,將原表數(shù)據(jù)拆分為一個chunk一個chunk,并且添加到數(shù)據(jù)遷移任務(wù)隊列中
通過binlog獲取原表的DML語句,并且添加到binlog重播任務(wù)隊列中
處理數(shù)據(jù)遷移任務(wù)隊列和binlog重播任務(wù)隊列,并將其順序的應(yīng)用到ghost表上(當(dāng)遇到節(jié)流操作或者h(yuǎn)int提示時,將會暫停該操作)
當(dāng)數(shù)據(jù)遷移與binlog重播完成后,將會在changelog表上注入/攔截"copy all done"的記錄
當(dāng)-postpone-cut-over-flag-file參數(shù)設(shè)置的文件存在時,將會推遲接下來的cut-over操作(但是原表的DML操作依舊會通過binlog應(yīng)用到ghost表上)
結(jié)束操作:交換表流程
將原表加上寫鎖,binlog事件會繼續(xù)應(yīng)用在gh-ost上(該步驟是個異步操作,因此即使表被鎖住,gh-ost仍然可以處理隊列中未處理完的binlog事件)
-
將原表rename為_tablename_del表,ghost則rename為tablename表
rename /* gh-ost */ table `wing`.`t` to `wing`.`_t_del`, `wing`.`_t_gho` to `wing`.`t` 清理工作:刪除需要被清除的表
異步設(shè)計優(yōu)點
Cut-over階段
異步設(shè)計最復(fù)雜的地方在于cut-over階段:原表和ghost表的交換。在同步設(shè)計中,由于原表操作與觸發(fā)器操作是在同一個事物空間中的,所以原表和ghost表的數(shù)據(jù)始終是同步的,因此一個簡單的原表和ghost表交換(Rename)是可以存在的。
在異步設(shè)計中,即使我們對原表加鎖,管道中仍然會存在一些事件,binlog日志依舊會將來自原表的事件重播到ghost表上。采用同步設(shè)計中交換表的方式是不可取的,因為這意味著,即使還沒有對來自原表的事件重播完畢,就開始使用重命名后的ghost表了,這將造成數(shù)據(jù)不一致。
Facebook的使用"中斷機(jī)制",二步重命名法:
鎖住原表,處理積壓的事件(backlog)
將原表重命名
將ghost重命名為原表的名字
在兩個表交換的時候,會有一個表不存在的階段,因此會存在"表中斷"的問題。
gh-ost通過"two-step"算法解決這個問題,"two-step"算法會阻塞表寫入,然后將兩表交換。它使操作很安全,要么成功,要么失敗則回滾到cut-over階段之前。
更多的信息請閱讀cut-over
分離去耦
不使用觸發(fā)器的異步設(shè)計最大的影響在于工作負(fù)載的去耦。使用觸發(fā)器的設(shè)計,不管是同步還是異步方法,原表上的每一個寫入意味著需要立刻在另外一張表上寫入。
We will break down the meaning of workload decoupling, shortly. But it is important to understand that gh-ost interprets the situation in its own time and acts in its own time, yet still makes this an online operation.
The decoupling is important not only as the tool's logic goes, but very importantly as the master server sees it. As far as the master knows, write to the table and writes to the ghost table are unrelated
寫負(fù)載
不使用觸發(fā)器意味著主庫不需要有過多的寫負(fù)載用在存儲過程上,以及對gh-ost表的鎖爭用上。
將原表操作重播到ghost表上完全由gh-ost工具完成。因此gh-ost可以決定何時將數(shù)據(jù)寫入到ghost表中。為了分解原表的寫負(fù)載,gh-ost工具選擇使用一個單獨的線程將原表操作重播到ghost表上。
MySQL對一個表大量并發(fā)寫入的時候性能不是很好,這個時候鎖變成了一個很大的問題。This is why we choose to alternate between the massive row-copy and the ongoing binlog events backlog such that the server only sees writes from a single connection。
更有趣的是,gh-ost是唯一寫入到ghost表的程序,沒有人意識到ghost表的存在。因此,gh-ost工具不存在由觸發(fā)器產(chǎn)生的高并發(fā)性問題以及資源高爭用問題。
可暫停性
當(dāng)gh-ost暫停工作(節(jié)流導(dǎo)致),此時將會沒有任何數(shù)據(jù)寫入到ghost表中。因為gh-ost不存在觸發(fā)器,寫負(fù)載是與gh-ost寫負(fù)載分開的。并且由于gh-ost使用異步設(shè)計的方法,gh-ost算法已經(jīng)處理了主庫寫入與ghost表寫入的時間差。對于gh-ost來說,幾毫秒的時間差與幾小時的時間差并沒有任何區(qū)別,對于gh-ost的運行并沒有任何的影響。
當(dāng)gh-ost進(jìn)行節(jié)流操作的時候,不管是因為主從復(fù)制延遲,還是達(dá)到max-load設(shè)置閥值等,原表還是正常操作。僅僅只是對ghost表沒有任何的寫操作。除了changelog表上的heartbeat在不斷的更新,但這個操作帶來的性能影響是可以忽略不計的。
可測試性
我們甚至可以測試數(shù)據(jù)遷移(migration)步驟:就像我們將數(shù)據(jù)遷移的操作與主庫的負(fù)載分開一樣,我們不在主庫上應(yīng)用所有的變更,我們選擇一個從庫,這樣我們可以在從庫上進(jìn)行表的數(shù)據(jù)遷移(migration)。
這本身是一個很不錯的功能;它為我們提供了測試的可能性:正如我們完成數(shù)據(jù)遷移一樣,我們從庫的復(fù)制(stop slave)。gh-ost會進(jìn)行cut-over階段,但是gh-ost也會回滾回去。gh-ost測試時不會刪除任何的表。結(jié)果是從庫上的原表和ghost表都會存在,也不會做進(jìn)一步的變更操作(因為此時主從復(fù)制已經(jīng)停止)。我們可以對兩張表進(jìn)行對比。
這個方法可以用于驗證gh-ost工具的正確性:在多個生產(chǎn)從庫上不斷的重復(fù)的做"數(shù)據(jù)遷移"(實際上并不會修改列)。每次數(shù)據(jù)遷移后都對原表和ghost表做一次數(shù)據(jù)校驗。gh-ost預(yù)計是所有的表數(shù)據(jù)校驗都是一致的。
多表并發(fā)操作
gh-ost可以運行多個不同的表并發(fā)操作(當(dāng)然不是在相同的表上并發(fā)操作)。gh-ost異步設(shè)計的方法是支持多個不同的表并發(fā)操作的。事實上沒有觸發(fā)器的存在,多個不同的表并發(fā)操作gh-ost對于主庫來說,只是并發(fā)的多個連接而已。每個gh-ost都可以控制自己的節(jié)流,或者全部一次性控制它們的節(jié)流操作。
Going outside the server space
More to come as we make progress
異步設(shè)計缺點
增加流量
現(xiàn)有的工具都是通過觸發(fā)器來重播原表上的操作。gh-ost是通過自己來獲取原表操作,然后重播到gh-ost表上。gh-ost當(dāng)然更喜歡在從庫上獲取原表操作,然后在主庫上重播到gh-ost表上。這也意味著,主庫機(jī)器和從庫機(jī)器之間存在數(shù)據(jù)的傳輸。并且gh-ost使用的MySQL客戶端不支持壓縮功能, and so during a migration you can expect the full volume of a table to transfer on the wire。
增加代碼復(fù)雜性
基于觸發(fā)器同步方法的online DDL工具相對來說代碼較少。大量的數(shù)據(jù)遷移是基于觸發(fā)器完成的。回滾,數(shù)據(jù)類型以及cut-over階段都是由數(shù)據(jù)庫隱式處理的。gh-ost的異步方法讓它的代碼變的更復(fù)雜。它分別連接到主庫和從庫,偽裝成從庫,向主庫寫入心跳事件,在從庫上讀取binlog事件并寫入到主庫上,它還需要管理連接失敗,主從復(fù)制延遲等等。
因此,gh-ost擁有更大的代碼庫以及更復(fù)雜的異步并發(fā)邏輯。
總結(jié)
以上是生活随笔為你收集整理的[翻译]Triggerless design.md的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【NOIP】提高组2012 同余方程
- 下一篇: 移除单链表的倒数第N个节点