Mysql online DDL(GH-OST)初嘗試
MySQL的大表DDL操作一直是比較頭疼的問題,因為DDL操作會鎖表影響業務操作,為保障業務連續性不受影響,所以線上DDL操作就很有必要。最近有幸在工作中接觸到這類需求。記錄一下。
gh-ost介紹:
gh-ost(Pronunce: ghost),即 gitHub’s online schema transformer,是github使用go語言開發的,專門用於資料庫線上表定義操作(線上DDL操作),其。
原理:
簡而言之,①建立滿足要求的ghost table(臨時表);②從源表複製行資料;③重演binlog日誌到ghost table;④用臨時表替換源表。
特性:
- 無觸發器
不像Percona的、 Facebook的 和 都是基於觸發器。gh-ost是基於binlog來監聽表中的資料變更。所以它是非同步的,只有源表的資料被提交後才會將變更同步到ghost table(臨時表)
- 輕量級(無侵入)
同樣得益於沒有無觸發器的好處,無需建立觸發器,基於binlog重演,同步資料。
- 可暫停
- 可動態控制
- 執行操作的過程中發現負載上升了,gh-ost可以通過Unix socket檔案或者tcp埠(可配置)的方式來監聽請求。
操作者可以在命令執行後更改相應的引數,參考下面的例子:
#限流 echo throttle | socat - /tmp/gh-ost.sock #開啟限速,同樣的,可以使用 no-throttle 來關閉限流。 echo no-throttle | socat - /tmp/gh-ost.test.b.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
- 可審計
- 可測試
- 值得信賴
操作模式(三種):
1)連線到從庫,在主庫上做遷移(DDL)(預設的方式)
- 源表歷史資料複製到ghost table在主庫進行讀寫;
- 變更從庫的二進位制日誌(binlog),將資料的新變更應用到主庫ghost table;
- 在從庫收集表格式、欄位、行數等資訊
- 在從庫內部讀取變更事件(如心跳時間)
- 在主庫切換表(ghost table rename成源表名)
2)連線到主庫,在主庫做遷移
資料複製、binlog重演、切表都是在主庫上執行。此時需要持續關注複製延遲的問題
前提:①主庫的二進位制日誌必須是RBR格式;②必須制定--allow-on-master引數;
3)在從庫遷移/測試
該模式會在從庫執行遷移操作。gh-ost 會簡單的連線到主庫,此後所有的操作都在從庫執行,不會對主庫進行任何的改動。整個操作過程中,gh-ost 將控制速度保證從庫可以及時的進行資料同步
--migrate-on-replica 表示 gh-ost 會直接在從庫上進行遷移操作。即使在複製執行階段也可以進行表的切換操作。
--test-on-replica 表示 遷移操作只是為了測試在切換之前複製會停止,然後會進行切換操作,然後在切換回來,你的原始表最終還是原始表。兩個表都會儲存下來,複製操作是停止的。你可以對這兩個表進行一致性檢查等測試操作。
各個工具對比:
常用線上DDL的工具,還有pecorna pt-osc。兩者對比主要如下:
優點 | 缺點 | |
---|---|---|
pt-osc | 併發DML支援較好 | 基於觸發器,對庫的效能有一定影響 |
gh-ost | 對主機效能幾乎沒有影響,而且可控制,而且是基於binlog,不急於trigger | 對源表有一定要求,比如不支援外來鍵;要求binlog為row格式; |
實踐:
1.登入堡壘機(操作生產環境)
2.構建批量生成的gh-ost指令碼的 shell指令碼檔案
[appdeploy@********:/app/lry/onlineddl]$cat online_mcs_ords_task.sh
#!/bin/bash
echo ===partions====
>online_task.txt
ct=1000000000
cat dbmcsords | while read line
do
let ct++
i=`echo $line|awk '{print $1}'`
j=`echo $line|awk '{print $2}'`
echo $i $j $ct
echo "nohup /app/mysql-onlineddl-gh/gh-ost --host=$i --port=3306 --user='ghost' --password='******** --allow-on-master --database='"$j"' --table='tt_bar_record_escale_task' --alter='ADD COLUMN EXTEND_ATTACH_EXT mediumtext NULL COMMENT \"新統一擴充套件欄位\" AFTER EXTEND_ATTACH_34;' --max-load=Threads_running=30 --critical-load=Threads_running=1000 --chunk-size=1000 --initially-drop-ghost-table --initially-drop-old-table --timestamp-old-table --cut-over=default --exact-rowcount --concurrent-rowcount --replica-server-id=$ct --execute >$j.log 2>&1 &" >> online_task.txt
echo "" >> online_task.txt
done
選項註釋:
--allow-on-master | 針對mater節點做操作。更好的時間是針對slave或者replica操作 |
-alter string | alter語句(必填) |
-max-load string | Comma delimited status-name=threshold. e.g: 'Threads_running=100,Threads_connected=500'. When status exceeds threshold, app throttles writes |
-critical-load string | Comma delimited status-name=threshold, same format as --max-load. When status exceeds threshold, app panics and quits |
-chunk-size int | amount of rows to handle in each iteration (allowed range: 100-100,000) (default 1000) |
-initially-drop-ghost-table | Drop a possibly existing Ghost table (remains from a previous run?) before beginning operation. Default is to panic and abort if such table exists |
--initially-drop-old-table | Drop a possibly existing OLD table (remains from a previous run?) before beginning operation. Default is to panic and abort if such table exists |
--timestamp-old-table | Use a timestamp in old table name. This makes old table names unique and non conflicting cross migrations |
-cut-over string | choose cut-over type (default|atomic, two-step) (default "atomic") |
-exact-rowcount | 精確計算行數。actually count table rows as opposed to estimate them (results in more accurate progress estimation) |
-concurrent-rowcount | (with --exact-rowcount), when true (default): count rows after row-copy begins, concurrently, and adjust row estimate later on; when false: first count rows, then start row copy (default true) |
-replica-server-id uint | server id used by gh-ost process. Default: 99999 (default 99999) |
-execute | actually execute the alter & migrate the table. Default is noop: do some tests and exit |
3.分批執行online_task.txt的指令碼(每次儘量少點,比如40G的表,同時執行10個左右)。
4.jobs命令檢視online DDL執行情況