鎖表變更對業務甚至是致命的,DDL無鎖變更通過引入非觸發器的方式可以解決大表無鎖變更這個難題。本文介紹幾種無鎖結構變更方案的對比。
線上業務不建議直接進行DDL操作,通常有幾種做法來避免影響業務:
業務低峰期變更:
合適的變更視窗以及視窗長度直接影響變更結果。過大的表由於在變更視窗內未執行完成,仍將影響業務。
備庫修改後切換主備:
需要存在主備執行個體,並能夠在合適視窗進行主備切換。
Online修改工具:
PT-Online(PT-Online-Schema-Change):工作原理是建立和源表A一樣的表A_gst執行DDL操作,同時在A上建立一個DML觸發器,然後將A中的資料拷貝到A_gst,在拷貝過程中產生的增量變更就用觸發器完成同步更新。拷貝結束後執行兩張表的rename操作完成變更。
OSC(OnlineSchemaChange):工作原理和pt-online-schema-change基本一致,不同的地方是它採用的是非同步模式,在A_gst的基礎上建立了一張日誌表,觸發器的條目更新將直接落在日誌表中,後台進程將日誌表中的條目應用到A_gst表。這樣整個流程上是非同步,也能夠控制回放速度。
gh-ost:與上面兩種變更流程基本一致,但是沒有使用觸發器的設計,所以增量變更的資料來源不是觸發器,而是Binlog檔案。訂閱讀取該檔案中A表的變更記錄,將記錄解析並應用到A_gst表。這樣的資料對於gst表回放非常有利,Binlog中儲存的都是A表的記錄,易於直接讀取和應用。
說明關於觸發器,請參見有無觸發器對比。
關於DMS無鎖結構變更與gh-ost工具的優劣勢對比詳情,請參見DMS無鎖結構變更與gh-ost工具對比。
有無觸發器對比
有觸發器:
基於觸發器設計的工具代碼邏輯相對簡單,大部分資料上的工作交給了觸發器去完成,包含資料庫的隱式處理、資料類型以及切換等相關操作,簡化了進行即時表遷移的大量流程。
無觸發器:
無觸發器設計最大的優點是和資料庫的工作負載解耦。觸發器的設計無論何種情況下,源表的DML都會同時在另外一張表上同步操作。非觸發器設計將這個過程解耦,即新表的寫入和源表的寫入不存在直接依賴。
對比項 | 有觸發器 | 無觸發器 |
資料庫開銷 | 觸發器是一個預存程序,隨著業務的DML,觸發器的執行必然存在開銷,業務繁忙時更甚。 | 觸發器開銷佔用的問題不存在。 作為一個偽裝的SLAVE訂閱主、備的Binlog事件,將其中的源表事件過濾下來並回放到目標表。這個過程和源表的變更沒有任何關係,也不需要資料庫上任何預存程序等幹涉這個寫入。 |
鎖 | 觸發器將兩張表的操作關聯到一個事務空間中,所以鎖的競爭會增加,即一個事務中的兩張表鎖並集。觸發器的設計中拷貝資料和變更資料只能並行,無疑將會增加鎖競爭。 | 無觸發器解耦了源表和目標表的依賴,所以鎖競爭也就不複存在。 關於目標表上的拷貝和更新時的競爭,我們在邏輯上使用交叉執行的方式避免和降低鎖競爭,雖然會影響變更效率,但是很顯然降低了資料庫負載。 |
異常處理 | 觸發器的設計,意味著觸發器永遠保持運行無法暫停。當伺服器繁忙、主備延遲、異常等情況時,在變更流程中的任何一個階段都無法取消觸發器,強行取消將導致變更中斷或資料丟失,從而導致A_gst表資料不準確。 | 訂閱Binlog的線程隨時可以暫停或者放慢速度,在系統繁忙和主備延遲較大時對工作中的應用開啟節流,避免問題擴大。 |
可靠性驗證 | 在驗證方案上我們期望得到任務的預期時間等資訊,在備庫上建立觸發器並類比,前提需要在Statement模式下。 ROW模式下無法類比,因為在主庫上的觸發器產生的資料效果重放到了備庫上。另外,即使是Statement模式,MySQL的回放是單線程的,Statement的單線程執行無法類比、複現主庫上的並發情境,也就無法驗證和測試並發和鎖相關的問題。 | 基於Binlog在主庫和備庫上操作Online沒有任何區別,避免對線上業務的幹擾或資源爭用。另外,通過在備庫上類比操作變更,實際並不切換源表和目標表,可以對源表和目標做校正來持續驗證可靠性。 |
代碼複雜性 | 主要依賴觸發器的同步和資料庫內部操作,工具的作用相對較小。 | 非觸發器的設計基於Binlog,有很大的自由度,但是複雜度會大幅增加。 需要註冊為一個SLAVE、訂閱事件並轉為SQL重新寫入,異常處理相對簡單的如處理串連失敗、複寫延遲以及資料類型等,其他程式的異常諸如程式負載、不可控異常等都要在代碼上進行關注。同時邏輯中需要包含大量的代碼以及更複雜的並發控制邏輯。 |
網路流量 | 觸發器在資料庫的內部處理資料。 | 非觸發器需要訂閱事件流以及回寫資料,這將使用到主機間的流量,佔用MySQL的進程流量。 代碼的複雜性依賴縝密的演算法邏輯,完善的測試案例集來保證健壯性和穩定性。但是相比之下,它帶來了更多的好處,比如可以指定時間切表、拷貝或者增量流量控制等一些額外的功能。 |
DMS無鎖結構變更與gh-ost工具對比
DMS無鎖結構變更與同樣採用無觸發器的gh-ost工具的優劣勢對比:
對比項 | DMS無鎖結構變更 | gh-ost | |
全量拷貝階段 | 拷貝限流 | Y:手動或自動 | Y:手動 |
資料一致性校正 | Y | N | |
異常容錯 | Y | Y:部分支援 | |
拷貝效能自適應 | Y | N | |
增量回放階段 | 回放限流 | Y:手動或自動 | Y:手動 |
多線程回放 | Y | N | |
資料一致性校正 | Y | N | |
異常容錯 | Y | Y:部分支援 | |
回放效能自適應 | Y | N | |
備庫訂閱 | N | Y | |
切換表階段 | 切換原子性 | Y | Y |
表副本延遲刪除 | Y | N | |
切換視窗設定 | Y | Y | |
鎖保護機制 | Y | N | |
功能性 | 備庫變更 | N | Y |
DTS(資料轉送)無縫銜接 | Y | N | |
變更原則設定(DDL演算法識別) | Y | N | |
RocksDB引擎 | Y | N | |
ToKuDB引擎 | Y | N | |
InnoDB引擎 | Y | Y | |
虛擬列變更 | Y | N | |
Json列變更 | Y | Y | |
多值索引和函數索引 | Y | - | |
最佳化資料表空間(Optimize) | Y | N | |
表副本延遲刪除 | Y | N | |
安裝部署 | Y:免安裝 | Y:本地安裝 | |
白屏化營運 | Y | N | |
執行進度可視化 | Y | N |
Y:支援該功能。
N:不支援該功能。
-:不明確是否支援該功能。