作者介绍
娄帅,北京万里开源公司数据库技术专家,擅长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