MySQL5.6 GTID新特性實踐 • cenalulu's Tech Blog
本文將簡單介紹基於5.6 GTID的主從複製原理的搭建。並通過幾個實驗介紹相關故障的處理方式
GTID簡介
什麼是GTID
GTID(Global Transaction ID)是對於一個已提交事務的編號,並且是一個全域性唯一的編號。 GTID實際上是由UUID+TID組成的。其中UUID是一個MySQL例項的唯一標識。TID代表了該例項上已經提交的事務數量,並且隨著事務提交單調遞增。下面是一個GTID的具體形式
更詳細的介紹可以參見:官方文件
GTID的作用
那麼GTID功能的目的是什麼呢?具體歸納主要有以下兩點:
- 根據GTID可以知道事務最初是在哪個例項上提交的
- GTID的存在方便了Replication的Failover
這裡詳細解釋下第二點。我們可以看下在MySQL 5.6的GTID出現以前replication failover的操作過程。假設我們有一個如下圖的環境
此時,Server A
的伺服器宕機,需要將業務切換到Server B
上。同時,我們又需要將Server C
的複製源改成Server B
。複製源修改的命令語法很簡單即CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS=nnnn
Server C
當前同步停止點,對應Server B
的master_log_file
和master_log_pos
是什麼的時候就成為了難題。這也就是為什麼M-S複製叢集需要使用MMM
,MHA
這樣的額外管理工具的一個重要原因。
這個問題在5.6的GTID出現後,就顯得非常的簡單。由於同一事務的GTID在所有節點上的值一致,那麼根據Server C
當前停止點的GTID就能唯一定位到Server B
上的GTID。甚至由於MASTER_AUTO_POSITION
功能的出現,我們都不需要知道GTID的具體值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION
搭建
本次搭建使用了mysql_sandbox
指令碼為基礎,先建立了一個一主三從的基於位置複製的環境。然後通過配置修改,將整個架構專為基於GTID的複製。如果你還不熟悉mysql_sandbox
,可以閱讀部落格之前的文章部落格之前的文章一步步的安裝。
根據MySQL官方文件給出的GTID搭建建議。需要一次對主從節點做配置修改,並重啟服務。這樣的操作,顯然在production環境進行升級時是不可接受的。Facebook
,Booking.com
,Percona
都對此通過patch做了優化,做到了更優雅的升級。具體的操作方式會在以後的博文當中介紹到。這裡我們就按照官方文件,進行一次實驗性的升級。
主要的升級步驟會有以下幾步:
- 確保主從同步
- 在master上配置read_only,保證沒有新資料寫入
- 修改master上的
my.cnf
,並重啟服務 - 修改slave上的
my.cnf
,並重啟服務 - 在slave上執行
change master to
並帶上master_auto_position=1
啟用基於GTID的複製
由於是實驗環境,read_only和服務重啟並無大礙。只要按照官方的GTID搭建建議做就能順利完成升級,這裡就不贅述詳細過程了。下面列舉了一些在升級過程中容易遇到的錯誤。
常見錯誤
gtid_mode=ON
,log_slave_updates
,enforce_gtid_consistency
這三個引數一定要同時在my.cnf
中配置。否則在mysql.err
中會出現如下的報錯
change master to 後的warnings
在按照文件的操作change master to
後,會發現有兩個warnings。其實是兩個安全性警告,不影響正常的同步(有興趣的讀者可以看下關於該warning的具體介紹。warning的具體內容如下:
實驗一:如果slave所需要事務對應的GTID在master上已經被purge了
根據show global variables like '%gtid%'
的命令結果我們可以看到,和GTID相關的變數中有一個gtid_purged
。從字面意思以及 官方文件可以知道該變數中記錄的是本機上已經執行過,但是已經被purge binary logs to
命令清理的gtid_set
。
本節中我們就要試驗下,如果master上把某些slave還沒有fetch到的gtid event purge後會有什麼樣的結果。
以下指令在master上執行
在slave2上重新做一次主從,以下命令在slave2上執行
實驗二:忽略purged的部分,強行同步
那麼實際生產應用當中,偶爾會遇到這樣的情況:某個slave從備份恢復後(或者load data infile)後,DBA可以人為保證該slave資料和master一致;或者即使不一致,這些差異也不會導致今後的主從異常(例如:所有master上只有insert沒有update)。這樣的前提下,我們又想使slave通過replication從master進行資料複製。此時我們就需要跳過master已經被purge的部分,那麼實際該如何操作呢? 我們還是以實驗一的情況為例:
先確認master上已經purge的部分。從下面的命令結果可以知道master上已經缺失24024e52-bd95-11e4-9c6d-926853670d0b:1
這一條事務的相關日誌
在slave上通過set global gtid_purged='xxxx'
的方式,跳過已經purge的部分
可以看到此時slave已經可以正常同步,並補齊了24024e52-bd95-11e4-9c6d-926853670d0b:2-3
範圍的binlog日誌。