背景
项目在使用Inception的时候,对于大表需要考虑对延迟的控制,会使用到pt-online-schema-change的–recursion-method。
公司在使用RDS数据库,故对于osc只能使用–recursion-method=dsn这种方式。目前inception不支持这种方式,故研究其代码。
同时也是对MySQL set variable这个SQL对应的背后知识有源码层次的了解。
本篇目前在RDS数据库情况,使用Inception对于大表alter的操作保护方案,支持指定从库IP列表的dsn方式。
MySQL gdb调试
1 | gdb --args /usr/local/mysql/bin/Inception --defaults-file=/usr/local/mysql/etc/inception.cnf |
针对gdb过程中遇到的 optimized out,参照How to compile without optimizations -O0 using CMake进行处理。
选择方式在CMakeLists.txt中加入:
1 | SET(CMAKE_CXX_FLAGS "-O0 -g3 -gdwarf-2") |
以枚举变量为例
变量类型
作用域 | 类型 | 存储地方 | 涉及文件 |
---|---|---|---|
Session | SESSION_VAR | struct system_variables | sql/sql_class.h |
Global | GLOBAL_VAR | 按照类型存储 | sql/mysqld.cc和sql/mysqld.h |
set variable调用关系
1 | (gdb) bt |
在find_type中会对参数进行比较进行比较,判断字符串是否和符合预期,不符合预期报语法错误。
支持recursion_method
代码分析
在Inception中使用Sys_var_enum类型支持recursion_method的设置。
这是一个枚举类型,只支持固定的值。
1 | const char *osc_recursion_method[]= {"processlist", "hosts", "none", "dsn", NullS}; |
对osc_recursion_method加dsn之后,可以设置inception_osc_recursion_method为dsn,否则报错。
1 | mysql> inception set inception_osc_recursion_method='dsn'; |
但是实际pt-osc在设置dsn为如下模式:
1 | dsn=h=192.40.120.26,P=4500,D=dpadmin,t=dsns_5627 |
这个不是一个固定的值,而是随着操作端口的不同,t的值是可以变化的,例如dsns_4300。
所以这里无法使用enum类型的,如果支持这种的话,需要使用Sys_var_charptr类型。
将enum修改为string类型
两者变量继承关系
- Sys_var_charptr
- Sys_var_enum
Sys_var_charptr只支持Global变量
修改代码
- 修改sql/mysqld.h
1 | extern char* inception_osc_recursion_method; |
- 修改sql/mysqld.cc
Global变量需要修改sql/mysqld.cc,Session级别变量在sql/sql_class.h中定义即可。
1 | //Added by Guosong 20180905 START |
- sql/sys_var.cc
1 | //Modified by Guosong START 20180905 |
- 修改sql/sql_parse.cc
1 | sprintf(cmd_line, "--recursion-method=%s", |
- 测试
1 | mysql> inception set inception_osc_recursion_method='processlist'; |
- 改成Global ReadOnly更合适
1 | static Sys_var_charptr Sys_inception_osc_recursion_method( |
1 | mysql> inception get variables 'inception_osc_recursion_method'; |
这种方式可以支持dns的方式,不过需要操作的主库存在dpadmin.dsns表,其保存对应的从库IP列表,用于操作大表的保护工作。