鎖表變更對業務甚至是致命的,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:不支持該功能。
-:不明確是否支持該功能。