一條會施魔法的MySQL命令: STOP ALL SLAVES
作者介紹
婁帥,北京萬裏開源公司數據庫技術專家,擅長MySQL運維及源碼研究。《Learning HBase》中文譯者。
原文:Playing with MySQL Source code; Adding “STOP ALL SLAVES” command,鏈接:https://mysql.az/2016/10/31/playing-with-mysql-source-code-adding-stop-all-slaves-command/
本文所要實現的功能來源於Charles Bell出版的《Expert MySQL》一書。《Expert MySQL》揭示了MySQL5.6.X版本的技術內幕,技術相對比較新且內容非常實用的一本書。
這裏要實現的功能是:
第八章“Extending MySQL High Availability”,第130頁,“Extending Replication”的功能。即添加一個新的命令“SQLCOM_STOP_SLAVES”,在master上執行,來停止所有的slave。實現方式是在master上執行"STOP ALL SLAVES"命令,通過binlog傳遞給slave並應用。
這裏基於MySQL5.6.32進行修改。
按照書中的提示,首先修改sql/lex.h文件,此文件中的符號數組是按照字母順序排序的。
修改如下:
然後修改sql/sql_cmd.h文件,添加新的枚舉類型,在文件的開頭可以找到enum_sql_command定義。
修改如下:
接著需要添加新的語法中用到的標記。這裏的標記也是按照字母順序排序的。打開sql/sql_yacc.yy文件,定位到對應的位置,添加我們新命令中需要的標記,這裏起名為SLAVES。
1539/1540行修改如下:
繼續修改“%type”定義的所在的段,將新標記添加進去。
1855/1856行修改如下:
然後在命令列表裏麵添加新的命令,這樣解析器就可以解析到新的語法規則。注意,這裏我們使用'|'來添加新的規則。
2079/2080行修改如下:
最後,我們添加新的語法規則來對應STOP ALL SLAVES命令。此規則隻需要將lex->sql_command設置為我們新增的枚舉類型即可。這樣就將語法的處理結果對應到最外層的命令處理函數的switch中的具體的枚舉值。
8114/8115行修改如下:
YACC文件到此修改完成,下麵我們需要在switch中添加對應的新分支,完成寫binlog事件的操作。正常情況下,STOP SLAVE操作是不會被複製的。我們的代碼需要突破這個限製。打開sql/sql_parse.cc文件,添加新的case分支。
3159/3160行修改如下:
if條件用來判斷是否可寫binlog文件,如果可以寫,我們就將“STOP SLAVE IO_THREAD”事件寫到binlog中,注意,我們這裏使用了特殊的STOP SLAVE命令,僅僅是停止SLAVE的IO線
程。
這裏假設讀者已經熟悉如何編譯MySQL源碼。如果不會,請參
考-https://mysql.az/2015/08/18/installing-mysql-from-source-cmake-issues/
直接運行make,結果出現如下錯誤:
作為源碼初學者,竟然意外的發現了書的bug。
看到了sql/sql_cmd.h文件中的如下注釋之後:
了解到,新的命令需要添加到sql/mysqld.cc文件。但是並沒有找到 struct show_var_st status_vars[]數組,取而代之的是SHOW_VAR com_status_vars[],參見#83613。
修改mysqld.cc文件的3571/3572行:
保存後重新編譯,成功了!下麵就是部署住主從複製集群來測試添加的新功能。書中作者使用了“MySQL Utilities“來部署。這裏我使用了“MySQL Sandbox”:
這樣,一主兩從的集群就部署完成,可以進行測試了。
不幸的是,“stop all slaves”執行失敗,master出現了斷言錯誤:
正常情況下,master執行完命令,應該返回Query OK。谘詢的Weixiang Zhai後,添加my_ok(thd)進行修複:
最終的sql/sql_parse.cc修改代碼如下:
重新編譯並進行測試,master運行新增命令結果如下:
slaves上的狀態如下:
像施了魔法一樣。
原文發布時間為:2016-11-23
本文來自雲棲社區合作夥伴DBAplus
最後更新:2017-05-11 12:01:32