MySQL在線DDL gh-ost 使用說明

背景:

      做爲一個DBA,大表的DDL的變動大部分都是使用Percona的pt-online-schema-change,本文說明下另外一種工具gh-ost的使用:不依賴於觸發器,是由於他是經過模擬從庫,在row binlog中獲取增量變動,再異步應用到ghost表的。在使用gh-ost以前,能夠先看GitHub 開源的 MySQL 在線更改 Schema 工具【轉】文章或則官網瞭解其特性和原理。本文只對使用進行說明。html

說明:

1)下載安裝:https://github.com/github/gh-ost/tagsmysql

2)參數說明:gh-ost --helpgit

 View Codegithub

3)使用說明:條件是操做的MySQL上須要的binlog模式是ROW。若是在一個從上測試也必須是ROW模式,還要開啓log_slave_updates。根據上面的參數說明按照需求進行調整。sql

     環境:主庫:192.168.163.131;從庫:192.168.163.130segmentfault

DDL過程多線程

複製代碼

① 檢查有沒有外鍵和觸發器。
② 檢查表的主鍵信息。
③ 檢查是否主庫或從庫,是否開啓log_slave_updates,以及binlog信息  
④ 檢查gho和del結尾的臨時表是否存在
⑤ 建立ghc結尾的表,存數據遷移的信息,以及binlog信息等    
---以上校驗階段
⑥ 初始化stream的鏈接,添加binlog的監聽
---如下遷移階段
⑥ 建立gho結尾的臨時表,執行DDL在gho結尾的臨時表上
⑦ 開啓事務,按照主鍵id把源表數據寫入到gho結尾的表上,再提交,以及binlog apply。
---如下cut-over階段
⑧ lock源表,rename 表:rename 源表 to 源_del表,gho表 to 源表。
⑨ 清理ghc表。

複製代碼

1. 單實例上DDL: 單個實例至關於主庫,須要開啓--allow-on-master參數和ROW模式。架構

gh-ost --user="root" --password="root" --host=192.168.163.131  --database="test" --table="t1"  --alter="ADD COLUMN cc2 varchar(10),add column cc3 int not null default 0 comment 'test' " --allow-on-master  --execute

2. 主從上DDL併發

有2個選擇,一是按照1直接在主上執行同步到從上,另外一個鏈接到從庫,在主庫作遷移(只要保證從庫的binlog爲ROW便可,主庫不須要保證):app

gh-ost --user="root" --password="root" --host=192.168.163.130  --database="test" --table="t" --initially-drop-old-table --alter="ADD COLUMN y1 varchar(10),add column y2 int not null default 0 comment 'test' "  --execute

此時的操做大體是:

  • 行數據在主庫上讀寫

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

  • 在從庫收集表格式,字段&索引,行數等信息

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

  • 在主庫切換表

在執行DDL中,從庫會執行一次stop/start slave,要是肯定從的binlog是ROW的話能夠添加參數:--assume-rbr。若是從庫的binlog不是ROW,能夠用參數--switch-to-rbr來轉換成ROW,此時須要注意的是執行完畢以後,binlog模式不會被轉換成原來的值。--assume-rbr和--switch-to-rbr參數不能一塊兒使用。

3. 在從上進行DDL測試

gh-ost --user="root" --password="root" --host=192.168.163.130  --database="test" --table="t"  --alter="ADD COLUMN abc1 varchar(10),add column abc2 int not null default 0 comment 'test' " --test-on-replica  --switch-to-rbr --execute

參數--test-on-replica:在從庫上測試gh-ost,包括在從庫上數據遷移(migration),數據遷移完成後stop slave,原表和ghost表馬上交換然後馬上交換回來。繼續保持stop slave,使你能夠對比兩張表。若是不想stop slave,則能夠再添加參數:--test-on-replica-skip-replica-stop

上面三種是gh-ost操做模式,上面的操做中,到最後不會清理臨時表,須要手動清理,再下次執行以前果真臨時表還存在,則會執行失敗,能夠經過參數進行刪除:

複製代碼

--initially-drop-ghost-table:gh-ost操做以前,檢查並刪除已經存在的ghost表。該參數不建議使用,請手動處理原來存在的ghost表。默認不啓用該參數,gh-ost直接退出操做。

--initially-drop-old-table:gh-ost操做以前,檢查並刪除已經存在的舊錶。該參數不建議使用,請手動處理原來存在的ghost表。默認不啓用該參數,gh-ost直接退出操做。

--initially-drop-socket-file:gh-ost強制刪除已經存在的socket文件。該參數不建議使用,可能會刪除一個正在運行的gh-ost程序,致使DDL失敗。

--ok-to-drop-table:gh-ost操做結束後,刪除舊錶,默認狀態是不刪除舊錶,會存在_tablename_del表。

複製代碼

還有其餘的一些參數,好比:--exact-rowcount、--max-lag-millis、--max-load等等,能夠看上面的說明,具體大部分經常使用的參數命令以下:

gh-osc --user= --password= --host= --database= --table= --max-load=Threads_running=30, --chunk-size=1000 --serve-socket-file=/tmp/gh-ost.test.sock --exact-rowcount --allow-on-master/--test-on-replica --initially-drop-ghost-table/--initially-drop-old-table/--initially-drop-socket-file --max-lag-millis= --max-load='Threads_running=100,Threads_connected=500' --ok-to-drop-table

4)額外說明:終止、暫停、限速

gh-ost --user="root" --password="root" --host=192.168.163.131  --database="test" --table="t1"  --alter="ADD COLUMN o2 varchar(10),add column o1 int not null default 0 comment 'test' " --exact-rowcount --serve-socket-file=/tmp/gh-ost.t1.sock --panic-flag-file=/tmp/gh-ost.panic.t1.flag  --postpone-cut-over-flag-file=/tmp/ghost.postpone.t1.flag --allow-on-master  --execute

① 標示文件終止運行:--panic-flag-file

建立文件終止運行,例子中建立/tmp/gh-ost.panic.t1.flag文件,終止正在運行的gh-ost,臨時文件清理須要手動進行。

② 表示文件禁止cut-over進行,即禁止表名切換,數據複製正常進行。--postpone-cut-over-flag-file

建立文件延遲cut-over進行,即推遲切換操做。例子中建立/tmp/ghost.postpone.t1.flag文件,gh-ost 會完成行復制,但並不會切換表,它會持續的將原表的數據更新操做同步到臨時表中。

③ 使用socket監聽請求,操做者能夠在命令運行後更改相應的參數。--serve-socket-file,--serve-tcp-port(默認關閉)

建立socket文件進行監聽,經過接口進行參數調整,當執行操做的過程當中發現負載、延遲上升了,不得不終止操做,從新配置參數,如 chunk-size,而後從新執行操做命令,能夠經過scoket接口進行動態調整。如:

暫停操做:

#暫停
echo throttle | socat - /tmp/gh-ost.test.t1.sock
#恢復
echo no-throttle | socat - /tmp/gh-ost.test.t1.sock

修改限速參數:

echo chunk-size=100 | socat - /tmp/gh-ost.t1.sock

echo max-lag-millis=200 | socat - /tmp/gh-ost.t1.sock

echo max-load=Thread_running=3 | socat - /tmp/gh-ost.t1.sock

 4)和pt-online-schema-change對比測試

 1. 表沒有寫入而且參數爲默認的狀況下,兩者DDL操做時間差很少,畢竟都是copy row操做。

 2. 表有大量寫入(sysbench)的狀況下,由於pt-osc是多線程處理的,很快就能執行完成,而gh-ost是模擬「從」單線程應用的,極端的狀況下,DDL操做很是困難的執行完畢。

 結論:雖然pt-osc不須要觸發器,對於主庫的壓力和性能影響也小不少,可是針對高併發的場景進行DDL效率仍是比pt-osc低,因此仍是須要在業務低峯的時候處理。相關的測試能夠看gh-ost和pt-osc性能對比

 5)封裝腳本:

環境:M:192.168.163.131(ROW),S:192.168.163.130/132

封裝腳本:gh-ost.py

 View Code

運行:

 View Code

總結:

gh-ost 放棄了觸發器,使用 binlog 來同步。gh-ost 做爲一個假裝的備庫,能夠從主庫/備庫上拉取 binlog,過濾以後從新應用到主庫上去,至關於主庫上的增量操做經過 binlog 又應用回主庫自己,不過是應用在幽靈表上。

gh-ost 首先鏈接到主庫上,根據 alter 語句建立幽靈表,而後做爲一個」備庫「鏈接到其中一個真正的備庫上,一邊在主庫上拷貝已有的數據到幽靈表,一邊從備庫上拉取增量數據的 binlog,而後不斷的把 binlog 應用回主庫。圖中 cut-over 是最後一步,鎖住主庫的源表,等待 binlog 應用完畢,而後替換 gh-ost 表爲源表。gh-ost 在執行中,會在本來的 binlog event 裏面增長如下 hint 和心跳包,用來控制整個流程的進度,檢測狀態等。這種架構帶來諸多好處,例如:

  • 整個流程異步執行,對於源表的增量數據操做沒有額外的開銷,高峯期變動業務對性能影響小。
  • 下降寫壓力,觸發器操做都在一個事務內,gh-ost 應用 binlog 是另一個鏈接在作。
  • 可中止,binlog 有位點記錄,若是變動過程發現主庫性能受影響,能夠馬上中止拉binlog,中止應用 binlog,穩定以後繼續應用。
  • 可測試,gh-ost 提供了測試功能,能夠鏈接到一個備庫上直接作 Online DDL,在備庫上觀察變動結果是否正確,再對主庫操做,內心更有底。

 

參考文檔:

https://github.com/github/gh-ost

GitHub 開源的 MySQL 在線更改 Schema 工具

Online DDL 工具 gh-ost 支持阿里雲 RDS

gh-ost:不同的在線表結構變動

GitHub開源MySQL Online DDL工具gh-ost參數解析 

相關文章
相關標籤/搜索