1. 程式人生 > >MySQL Online DDL工具

MySQL Online DDL工具

MySQL線上表結構變更工具

MySQL的大表表結構變更常用的解決方案無外乎三種:

一是利用Percona的pt-online-schema-change,Facebook的OSC等三方工具,

二是在備庫修改通過切換實現滾動變更,

三則是升級MySQL到5.6/5.7通過官方Online DDL實現部分變更。

然而,引入觸發器帶來的鎖競爭問題,主備切換帶來的附加成本以及Online DDL的侷限性都不讓DBA省心。

gh-ost不依賴於觸發器,通過模擬從庫,在row binlog中獲取增量變更,再非同步應用到ghost表。

gh-ost

gh-ost GitHub 的線上 Schema 修改工具,下面工作原理圖:

 

gh-ost 具有如下特性:

  • 無觸發器

  • 輕量級

  • 可暫停

  • 可動態控制

  • 可審計

  • 可測試

  • 值得信賴 

無觸發器

gh-ost 沒有使用觸發器。它通過分析binlog日誌的形式來監聽表中的資料變更。因此它的工作模式是非同步的,只有當原始表的更改被提交後才會將變更同步到臨時表(ghost table)

gh-ost 要求binlog是RBR格式 ( 基於行的複製);然而也不是說你就不能在基於SBR(基於語句的複製)日誌格式的主庫上執行線上變更操作。實際上是可以的。gh-ost 可以將從庫的 SBR日誌轉換為RBR日誌,只需要重新配置就可以了。

輕量級

由於沒有使用觸發器,因此在操作的過程中對主庫的影響是最小的。當然在操作的過程中也不用擔心併發和鎖的問題。 變更操作都是以流的形式順序的寫到binlog檔案中,gh-ost只是讀取他們並應用到gh-ost表中。實際上,gh-ost 通過讀取binlog的寫事件來進行順序的行復制操作。因此,主庫只會有一個單獨連線順序的將資料寫入到臨時表(ghost table)。這和ETL操作有很大的不同。

可暫停

所有的寫操作都是由gh-ost控制的,並且以非同步的方式讀取binlog,當限速的時候,gh-ost可以暫停向主庫寫入資料,限速意味著不會在主庫進行復制,也不會有行更新。當限速時gh-ost會建立一個內部的跟蹤(tracking)表,以最小的系統開銷向這個表中寫入心跳事件

gh-ost 支援多種方式的限速:

  • 負載: 為熟悉 pt-online-schema-change 工具的使用者提供了類似的功能,可以設定MySQL中的狀態閾值,如 Threads_running=30

  • 複製延遲: gh-ost 內建了心跳機制,可以指定不同的從庫,從而對主從的複製延遲時間進行監控,如果達到了設定的延遲閾值程式會自動進入限速模式。

  • 查詢: 使用者可以可以設定一個限流SQL,比如 SELECT HOUR(NOW()) BETWEEN 8 and 17 這樣就可以動態的設定限流時間。

  • 標示檔案: 可以通過建立一個標示檔案來讓程式限速,當刪除檔案後可以恢復正常操作。

  • 使用者命令: 可以動態的連線到 gh-ost (下文會提到) 通過網路連線的方式實現限速。

可動態控制

現在的工具,當執行操作的過程中發現負載上升了,DBA不得不終止操作,重新配置引數,如 chunk-size,然後重新執行操作命令,我們發現這種方式效率非常低。

gh-ost 可以通過 unix socket 檔案或者TCP埠(可配置)的方式來監聽請求,操作者可以在命令執行後更改相應的引數,參考下面的例子:

  • echo throttle | socat - /tmp/gh-ost.sock 開啟限速,同樣的,可以使用 no-throttle 來關閉限流。

  • 改變執行引數: chunk-size=1500max-lag-millis=2000max-load=Thread_running=30 這些引數都可以在執行時變更。

可審計

同樣的,使用上文提到的程式介面可以獲取 gh-ost 的狀態。gh-ost 可以報告當前的進度,主要引數的配置以及當前伺服器的標示等等。這些資訊都可以通過網路介面取到,相對於傳統的tail日誌的方式要靈活很多。

可測試

因為日誌檔案和主庫負載關係不大,因此在從庫上執行修改表結構的操作可以更真實的體現出這些操作鎖產生的實際影響。(雖然不是十分理想,後續我們會做優化工作)。

gh-ost 內建支援測試功能,通過使用 --test-on-replica 的引數來指定: 它可以在從庫上進行變更操作,在操作結束時gh-ost 將會停止複製,交換表,反向交換表,保留2個表並保持同步,停止複製。可以在空閒時候測試和比較兩個表的資料情況。

這是我們在GitHub的生產環境中的測試:我們生產環境中有多個從庫;部分從庫並不是為使用者提供服務的,而是用來對所有表執行的連續覆蓋遷移測試。我們生產環境中的表,小的可能沒有資料,大的會達到數百GB,我們只是做個標記,並不會正在的修改表結構(engine=innodb)。當每一個遷移結束後會停止複製,我們會對原表和臨時表的資料進行完整的checksum確保他們的資料一致性。然後我們會恢復複製,再去操作下一張表。我們的生產環境的從庫中已經通過 gh-ost 成功的操作了很多表。

值得信賴

上文提到說了這麼多,都是為了提高大家對 gh-ost 的信任程度。畢竟在業界它還是一個新手,類似的工具已經存在了很多年了。

  • 在第一次試手之前我們建議使用者先在從庫上測試,校驗資料的一致性。我們已經在從庫上成功的進行了數以千計的遷移操作。

  • 如果在主庫上使用 gh-ost 使用者可以實時觀察主庫的負載情況,如果發現負載變化很大,可以通過上文提到的多種形式進行限速,直到負載恢復正常,然後再通過命令微調引數,這樣可以動態的控制操作風險。

  • 如果遷移操作開始後預完成計時間(ETA)顯示要到夜裡2點才能完成,結束時候需要切換表,你是不是要留下來盯著?你可以通過標記檔案讓gh-ost推遲切換操作。gh-ost 會完成行復制,但並不會切換表,它會持續的將原表的資料更新操作同步到臨時表中。你第二天來到辦公室,刪除標記檔案或者通過介面 echo unpostpone 告訴gh-ost開始切換表。我們不想讓我們的軟體把使用者綁住,它應該是為我們拜託束縛。

  • 說到 ETA, --exact-rowcount 引數你可能會喜歡。相對於一條漫長的 SELECT COUNT(*) 語句,gh-ost 會預估出遷移操作所需要花費的時間,還會根據當前遷移的工作狀況更新預估時間。雖然ETA的時間隨時更改,但進度百分比的顯示是準確的。

gh-ost 操作模式

gh-ost 可以同時連線多個伺服器,為了獲取二進位制的資料流,它會作為一個從庫,將資料從一個庫複製到另外一個。它有各種不同的操作模式,這取決於你的設定,配置,和要執行遷移環境。

 

a. 連線到從庫,在主庫做遷移

這是 gh-ost 預設的工作方式。gh-ost 將會檢查從庫狀態,找到叢集結構中的主庫並連線,接下來進行遷移操作:

  • 行資料在主庫上讀寫

  • 讀取從庫的二進位制日誌,將變更應用到主庫

  • 在從庫收集表格式,欄位&索引,行數等資訊

  • 在從庫上讀取內部的變更事件(如心跳事件)

  • 在主庫切換表

如果你的主庫的日誌格式是 SBR,工具也可以正常工作。但從庫必須啟用二級制日誌(log_bin, log_slave_updates) 並且設定 binlog_format=ROW ( gh-ost 是讀取從庫的二級制檔案)。

如果直接在主庫上操作,當然也需要二進位制日誌格式是RBR。

b. 連線到主庫

如果你沒有從庫,或者不想使用從庫,你可以直接在主庫上操作。gh-ost 將會直接在主庫上進行所有操作。你需要持續關注複製延遲問題。

  • 你的主庫的二進位制日誌必須是 RBR 格式。

  • 在這個模式中你必須指定 --allow-on-master 引數

c. 在從庫遷移/測試

該模式會在從庫執行遷移操作。gh-ost 會簡單的連線到主庫,此後所有的操作都在從庫執行,不會對主庫進行任何的改動。整個操作過程中,gh-ost 將控制速度保證從庫可以及時的進行資料同步

  • --migrate-on-replica 表示 gh-ost 會直接在從庫上進行遷移操作。即使在複製執行階段也可以進行表的切換操作。

  • --test-on-replica 表示 遷移操作只是為了測試在切換之前複製會停止,然後會進行切換操作,然後在切換回來,你的原始表最終還是原始表。兩個表都會儲存下來,複製操作是停止的。你可以對這兩個表進行一致性檢查等測試操作。

gh-ost at GitHub

我們已經在所有線上所有的資料庫線上操作中使用了gh-ost ,我們每天都需要使用它,根據資料庫修改需求,可能每天要執行多次。憑藉其審計和控制功能我們已經將它整合到了ChatOps流程中。我們的工程師可以清醒的瞭解到遷移操作的進度,而且可以靈活的控制其行為。

開源

gh-ost 在MIT的許可下發布到了開源社群

https://www.cnblogs.com/zhoujinyi/p/9187502.html

https://yq.aliyun.com/articles/62928