# myonlineddl **Repository Path**: mysql3306/myonlineddl ## Basic Information - **Project Name**: myonlineddl - **Description**: 安全高效的改表平台,非常适用于搭建平台化改表系统。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 5 - **Created**: 2021-08-06 - **Last Updated**: 2021-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # myonlineddl ### 一、介绍 - 安全高效的改表平台,非常适用于搭建平台化改表系统。 - 支持建表/改表/删表/truncate等操作。 - 仅实现了后台逻辑,于前端无关,可以给前端提供api调用。 ### 软件架构 流程图如下 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0313/124302_3174a5b5_1658508.png "myonlineddl.png") #### 简单介绍 - 1、格式化SQL,需要将业务SQL做统一格式化处理,方便后面做SQL解析。 - 2、第一次SQL解析。根据用户提交的DDL做预定义用法判断,检查所有操作是否是满足预定义的。这块逻辑就是把控工单的操作,做到所有操作都可控。啥能做,啥不能做。 - 3、第二次SQL解析。判断单条DDL是否满足【Only Modifies Metadata】如果满足就直接OnlineDDL了,如果不满足就使用ghost/ptosc工具。选择工具的时候会针对上述的优缺点问题做各自的判断,然后优先选择ghost。说白了就是工单自适应,可根据当前操作,及不同环境做出判断,并调整相应配置生成一个安全合理又高效的执行计划。 - 4、提供DDL审核功能,并不是说业务提交什么就都能通过。比如说,是否允许null值,是否要求有注释,是否要求规范索引名等等。都可以通过规则开关进行审核。(这点跟上述得预定义用法判断有区别,一个是限制操作,一个是控制操作是否规范合理) - 5、加上监控,和对异常处理。比如对mdl的监控,连接数,活跃连接数,磁盘空间等等,触发告警会有邮件提示。 - 6、尽可能的保证每个工单的原子性。就是尽可能的保证每个工单里的每条DDL都成功。要么就都不做,要做就都要成功,需要注意,这里说的是尽可能,有点耐人寻味。 - 7、通过API去实现动态配置改表工单,比如正在执行的改表需要暂停,恢复,终止,又或者需要获取改表进度。 - 8、扫尾工作。这点没什么好说的,擦干屁股很重要,避免下次踩坑。 #### 如何实现     要实现上述功能,最大的难度就是如何对业务的DDL操作进行解析。只有实现了SQL解析,才能消除上痛点实现功能。大家也可以想想怎么实现SQL解析这个功能。现在提几个我在实现的时候遇到问题,供大家思考: - 1、SQL格式化的时候,注释会对你的实现会产生很大的阻碍,那么该如何处理注释的呢。( “/* */ comment '' # --”等等这些注释 ) - 2、SQL解析的时候要考虑【Only Modifies Metadata】分change、modify,varchar扩长度(又有局限性)等场景。如何鉴定这些是否满足【OMM】,如果是modify的组合模式(modify varchar and not varchar)又该怎么鉴定。 - 3、如何鉴定是否满足8.0的快速加列。 - 4、SQL审核的功能,如何把控DDL操作是合理的。 - 5、保留字问题怎么处理呢?不处理,直接返回错误?那用户体验太差了。有些人可能就会说,用反引号引起来就好了,那么问题来了,用户不知道这是关键字,他写的SQL没有用反引号,那需要工单系统二次处理给加上,那应该怎么加呢?哪些需要加呢? 以上几点,大家可以想想怎么实现,可能用脑子一过觉得难度好像不大,但是真正落实到代码,应该还是有些难度的。毕竟ALTER TABLE语法千变万化,组合十分复杂,关于我是如何实现的,有兴趣的小伙伴可以看一下代码,欢迎吐槽改进。 ### 二、安装教程 #### 1、获取项目 ``` git clone https://gitee.com/mo-shan/myonlineddl.git ``` > 建议放在/data/git/下面, 后面配置起来比较方便,就不用修改main.sh里面的work_dir变量了 - 目录结构如下: ``` centos1 root /data/git/myonlineddl >> ls -l total 5100 drwxr-xr-x 2 root root 4096 Mar 14 21:19 bin drwxr-xr-x 2 root root 4096 Jun 15 2021 conf drwxr-xr-x 12 root root 4096 Mar 14 18:31 function drwxr-xr-x 2 root root 4096 Jun 8 2021 html drwxr-xr-x 2 root root 4096 Mar 14 21:54 init drwxr-xr-x 2 root root 4096 Mar 14 21:58 logs -rw-r--r-- 1 root root 21275 Mar 14 20:06 main.sh -rw-r--r-- 1 root root 5168793 Mar 14 09:27 myonlineddlApi.tar.gz drwxr-xr-x 2 root root 4096 Mar 14 21:40 tmp centos1 root /data/git/myonlineddl >> centos1 root /data/git/myonlineddl >> tree -L 3 . ├── bin │   ├── gh-ost │   ├── msrt │   ├── pt-duplicate-key-checker │   ├── pt-online-schema-change │   ├── send_mail.py │   ├── socat │   └── timeout ├── conf │   └── myonlineddl.conf ├── function │   ├── analysis │   │   ├── f_delete_for_string.sh │   │   ├── f_get_alter_sql.sh │   │   ├── f_get_create_sql.sh │   │   ├── f_get_sql_file.sh │   │   └── f_return_alter_sql.sh │   ├── check │   │   ├── f_check_mode_opt.sh │   │   ├── f_check_net_delay.sh │   │   ├── f_check_osc_or_alter.sh │   │   ├── f_check_ssh_auth.sh │   │   └── f_check_work_is_run.sh │   ├── clean │   │   └── f_exit.sh │   ├── dbadb │   │   ├── f_check_diy_info.sh │   │   ├── f_get_diy_info.sh │   │   ├── f_print_progress_info.sh │   │   ├── f_record_info_to_dbadb.sh │   │   └── f_update_status_for_task.sh │   ├── log │   │   ├── f_archive_log.sh │   │   ├── f_logging.sh │   │   └── f_usage.sh │   ├── mail │   │   ├── f_check_mdl_and_send_mail.sh │   │   └── f_send_mail_for_alter_table_schedule.sh │   ├── monitor │   │   ├── f_check_connect.sh │   │   ├── f_check_daemonize.sh │   │   ├── f_check_disk_space.sh │   │   ├── f_check_mdl_lock_daemonize.sh │   │   └── f_check_mdl_lock.sh │   ├── mysql │   │   ├── f_check_mysql_info.sh │   │   ├── f_check_slave_status.sh │   │   ├── f_check_table_after_ddl.sh │   │   ├── f_check_table_and_disk_size.sh │   │   ├── f_clear_table.sh │   │   ├── f_create_test_env.sh │   │   ├── f_delete_tmp_table.sh │   │   ├── f_exe_alter_sql.sh │   │   ├── f_exe_osc_comm.sh │   │   ├── f_exe_sql_in_mysql.sh │   │   ├── f_get_mysql_node_info.sh │   │   └── f_support_onlineddl.sh │   ├── osctool │   │   ├── f_init_osc_opt.sh │   │   └── f_kill_process.sh │   └── prepare │   ├── f_init_dir.sh │   └── f_init_tmpvar.sh ├── html ├── init │   ├── env56.sql │   ├── env80.sql │   ├── myonlineddl.sql │   ├── test56.sql │   └── test80.sql ├── logs │   └── main.log ├── main.sh ├── myonlineddlApi.tar.gz └── tmp ├── alter_table.mstest.3307.123456 └── alter_table.mstest.3308.123456 17 directories, 60 files centos1 root /data/git/myonlineddl >> ``` - bin 可执行文件 - conf 配置文件 - function 函数文件 > - 每个目录里面的函数功能,大概跟文件名沾边 > - mysql 目录下面的文件,基本都是处理mysql相关的 > - check 目录就是检查相关的 > - monitor 就是监控相关的 > - analysis 就是sql解析相关 - html html文件,发邮件的时候会先生成html文件 - img 图片 - init 初始化sql - logs 日志文件 > - execute 表示在线上执行的任务的日志,日志命名规范是[pt-osc-sql文件名.log,gh-ost-sql文件名.log] > - test是测试环境输出的日志,日志命名规范是,同execute; > - script是脚本日志,日志命名规范是[sql文件名.log] - main.sh 主程序 - myonlineddlApi.tar.gz 项目 - tmp 临时目录,我一般会把本地的sql文件放在这里 #### 2、安装pt所需perl环境 ``` yum -y install perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL perl-CPAN perl-Digest-MD5 ``` #### 3、准备测试环境 - 需要MySQL测试环境,原则上线上有几个版本就需要有几个测试环境,按照版本对应,比如需要改8.0的表,就需要在8.0的测试环境预执行。 > 如果没有找到对应的测试环境,改表会报错并终止。 > 另外需要给测试环境的用户所有权限, 因为改表过程中需要建库,建表,删库,删表。 > 权限请参考init/test56.sql等文件 ``` centos1 root /data/git/myonlineddl >> ll init/ total 32 -rw-r--r-- 1 root root 564 Jun 15 2021 env56.sql -rw-r--r-- 1 root root 752 Jun 15 2021 env80.sql -rw-r--r-- 1 root root 12568 Mar 14 18:34 myonlineddl.sql -rw-r--r-- 1 root root 91 Jun 15 2021 test56.sql -rw-r--r-- 1 root root 278 Jun 15 2021 test80.sql centos1 root /data/git/myonlineddl >> cat init/test56.sql grant all on *.* to myonlineddl@'192.168.%' identified by 'myonlineddlpassword'; -- 授权 centos1 root /data/git/myonlineddl >> cat init/test80.sql create user if not exists myonlineddl@'192.168.%' identified by 'myonlineddlpassword'; -- 创建用户8.0 grant all on *.* to myonlineddl@'192.168.%'; -- 授权 centos1 root /data/git/myonlineddl >> ``` #### 4、准备mysql环境 - 安装的机器要有mysql环境,很多命令依赖于mysql客户端工具。 #### 5、准备msrt环境 - 如果没有ssh环境需要部署这个工具,用于代替ssh,主要是采集mysql节点的磁盘监控。 - 如果没有ssh免密环境又没有部署这个工具,则不会监控磁盘空间,建议部署。 - 到目标节点运行如下命令即可,注意需要给每个mysql节点部署。 编辑帮助
> - 这里的pass选项需要对应后面的配置文件中的密码,否则将通讯失败 > - 该工具可以自行修改,修改完直接make重新编译即可 https://gitee.com/mo-shan/msrt.git #### 6、python 2.7环境 - api依赖于2.7环境,读者也可以根据自己实际情况开发api环境,将view拷贝过去即可。 > 下面介绍api环境的部署 - 随包有个myonlineddlApi.tar.gz,解压到/data/git - 进入目录解压py27env.tar.gz虚拟环境即可,也可自己搭建虚拟环境然后pip install -r requirements.txt - 修改配置 ``` centos1 root /data/git/myonlineddl/myonlineddlApi >> cat conf/config.ini [MySQL] mysql_host = 192.168.1.10 mysql_port = 3306 mysql_user = myonlineddl mysql_pass = myonlineddlpassword mysql_db = myonlineddl mysql_table = "dbadb_alter_table_repl_time" centos1 root /data/git/myonlineddl/myonlineddlApi >> ``` > 请根据实际情况进行修改dbadb环境的连接信息 - 使用虚拟环境运行app.py即可。 编辑帮助
> 可以通过如下方式去访问接口,然后进行改表状态的控制 编辑帮助
> 这里是因为当前这个工单没有该表任务,所以提示这个。 #### 7、检查socat环境 - 动态调整改表状态需要这个工具。 ``` centos1 root /data/git/myonlineddl >> ./bin/socat --help ./bin/socat: error while loading shared libraries: libreadline.so.5: cannot open shared object file: No such file or directory centos1 root /data/git/myonlineddl >> ``` > 如果报错请参考下面的操作进行安装配置 ``` centos1 root /data/git/myonlineddl >> yum -y install readline-devel readline centos1 root /data/git/myonlineddl >> cd /lib64 centos1 root /lib64 >> ll *libreadline* lrwxrwxrwx. 1 root root 18 Aug 22 2020 libreadline.so.6 -> libreadline.so.6.0 -rwxr-xr-x 1 root root 272008 Jun 21 2012 libreadline.so.6.0 centos1 root /lib64 >> ln -s /lib64/libreadline.so.6 /lib64/libreadline.so.5 centos1 root /lib64 >> ll *libreadline* lrwxrwxrwx 1 root root 23 Mar 14 00:18 libreadline.so.5 -> /lib64/libreadline.so.6 lrwxrwxrwx. 1 root root 18 Aug 22 2020 libreadline.so.6 -> libreadline.so.6.0 -rwxr-xr-x 1 root root 272008 Jun 21 2012 libreadline.so.6.0 centos1 root /lib64 >> ``` #### 8、编辑配置文件 - conf/myonlineddl.conf 编辑帮助
> - 请读者根据实际情况更新该文件 > - 改表用户要求有管理员权限,即 *.* 权限。也就是对应到配置文件中的【mysql_user】 > - 如果软件存放的目录不是/data/git/myonlineddl, 则需要改一下main.sh第一行代码的work_dir变量 #### 9、搭建dbadb环境 - dbadb环境可以理解为是改表需要保存元数据的地方,里面会有一些表,建议是独立的库。 编辑帮助
编辑帮助
> 对这些表中的两个做一些介绍,其余表可以自行查看建表语句,都有注释 > - dbadb_alter_table_repl_time 改表状态表,需要根据这个表去动态调整改表的状态,比如暂停,恢复,终止,改表任务开始后会在这个表写一行记录,api就是通过更新这行记录,然后程序实施监控这行记录是否被变更。 > - dbadb_drop_table_state_info 删表工单记录表,每个删表工单需要执行的sql都会保存到这里,延迟删除的话,crontab 也是读这个表的记录。 > - mysql_ins_rs mysql集群信息表,这个表记录了所有master - slave 信息,改表程序会根据用户传的端口去读这个表然后才知道去哪改表,所以要求每个集群端口唯一。 mysql_ins_rs > - 可以看到我这个环境有两套集群 3307 3308 > 另外,需要注意的是用户需要传递一个sql文件,文件保存的是ddl操作,文件名要求分几个段【alter_table.testdb.3306.1234456】,并且按照小数点分割: > - 1、动作,表示需要做啥操作,目前支持的是create_table 和alter_table > - 2、db名称, 需要告诉程序要改那个db的 > - 3、mysql端口, 通过这个端口去dbadb库里查 mysql_ins_rs 表, 获取到master及slave的相关信息。 > - 4、第四个段目前没有用,建议是时间戳,也可以随便什么字符,通过后面的测试也能看出来规则 #### 10、配置邮件服务 触发告警后是通过邮件发送告知,如果没有邮件服务器环境可以使用bin目录下的 send_mail.py脚本进行发送 > 建议使用163邮箱 编辑帮助
编辑帮助
> 这里只需要将实际的用户密码配上就行, 但是需要注意的是这个密码不是邮箱的登录密码,而是【客户端授权密码】,如果没有设置过需要开启一下,请参照如下图 编辑帮助
#### 11、配置crontab(可选) > 如果有延迟删除,延迟truncate等需求,需要配上crontab,要不然延迟操作将失效。 ``` #crontab里面添加如下规则,请根据实际情况配置 0 5 * * * bash /data/git/myonlineddl/main.sh -a crontab_drop -u 1005155691@qq.com #添加者:moshan,每天凌晨5点会读dbadb_drop_table_state_info 表,将符合条件的端口做删除操作 ``` ### 三、使用介绍 #### 1、使用帮助 > 通过上述几个步骤操作完成后可以通过查看一下参数介绍: ![使用帮助](https://images.gitee.com/uploads/images/2021/0314/205850_d6781d79_1658508.png "clipboard.png") > 功能介绍 ![功能介绍](https://images.gitee.com/uploads/images/2021/0314/210141_70bb6058_1658508.png "clipboard.png") ##### (1)改表操作介绍 ``` bash main.sh -h localhost -f tmp/alter_table.mstest.3308.123456 -u 1005155691@qq.com -O $(date +%s) ``` > - -h 必选。-h 的作用是可以从源端传sql文件,比如通过api调用的时候,通过rsync拉sql文件 > - -f 必选。如果-h是源端(非localhost),就会通过rsync拉取以if这个文件为名的文件。如果-h是localhost的时候-f指定的文件必须存在,否则会报错。 > - -u是用户的邮箱地址 > - -O是工单号, 建议使用时间戳 > - -e 可选0|1 默认是1,表示在线上执行,如果是0表示对这个操作进行check。不会到线上执行。 ##### (2)建表操作介绍 ``` bash main.sh -h localhost -f tmp/create_table.mstest.3308.123456 -u 1005155691@qq.com -O $(date +%s) ``` > 请参照改表参数介绍 ##### (3)删表操作介绍 ``` bash main.sh -a drop_table -D mstest -T "mstest,mstest1,mstest2,mstest3,mstest4,mstest5,mstest6" -O $(date +%s) -u 1005155691@qq.com -P 3307 ``` > - -a 必选 表示操作drop_table|truncate_table|later_drop_table|later_truncate_table > - -D dbname > - -T table list 逗号隔开 > - -O 工单号 > - -u 用户邮箱地址 > - -P 端口号 > - truncate_table|later_drop_table|later_truncate_table等操作,参数一样。带later标识表示延迟操作,会先rename成待删除表,然后三天后删除 > - 需要说明一下,延迟删除是通过crontab去实现的,所以需要部署一个crontab任务,如下 ``` centos1 root /data/git/myonlineddl >> crontab -l 0 5 * * * bash /data/git/myonlineddl/main.sh -a crontab_drop centos1 root /data/git/myonlineddl >> centos1 root /data/git/myonlineddl >> bash /data/git/myonlineddl/main.sh -a crontab_drop [ 2021-03-14 23:04:10 ] [ 提示 ] [ 192.168.1.10 ] [ f_main ] [ 开始执行 : 'main.sh -a crontab_drop' ] [ 2021-03-14 23:04:10 ] [ 警告 ] [ 192.168.1.10 ] [ f_check_mode_opt ] [ 本次操作是处理延迟删除遗留的待删除的任务 ] [ 2021-03-14 23:04:10 ] [ 提示 ] [ 192.168.1.10 ] [ f_check_mode_opt ] [ 开始执行 : 'main.sh ' ] [ 本次操作日志, 详情请看 : /data/git/myonlineddl/logs/script/.log ] [ 2021-03-14 23:04:17 ] [ 提示 ] [ 192.168.1.10 ] [ /data/git/myonlineddl/main.sh ] [ 执行结束 : -a crontab_drop ] centos1 root /data/git/myonlineddl >> ``` #### 2、用例介绍 - (1)测试用例1 - 8.0 > 改表前的表结构 ``` mysql> show create table mstest9\G *************************** 1. row *************************** Table: mstest9 Create Table: CREATE TABLE `mstest9` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `name1` char(50) DEFAULT NULL, `name2` varchar(50) DEFAULT NULL, `name3` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.00 sec) mysql> ``` > 出主键外,所有字段的长度都是50,但是name1是char类型,其余是varchar > 改表语句 ``` centos1 root /data/git/myonlineddl >> cat tmp/alter_table.mstest.3307.123456 alter table mstest9 modify name varchar(55) DEFAULT NULL, modify name1 varchar(55) DEFAULT NULL, modify name2 varchar(55) DEFAULT NULL, modify name3 varchar(55) DEFAULT NULL; centos1 root /data/git/myonlineddl >> ``` > varchar字段都扩了5个字符长度变成55,按照预期,不满足OMM,所以会选择ghost工具 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0314/213129_df7f4606_1658508.png "clipboard.png") > 可以看到日志中红色箭头部分,检测到name1 是char 到varchar类型的修改,不满足OMM操作, 所以需要用工具进行操作。 - (2)测试用例2 - 8.0 > 改表前的表结构 ``` mysql> show create table mstest9\G *************************** 1. row *************************** Table: mstest9 Create Table: CREATE TABLE `mstest9` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(55) DEFAULT NULL, `name1` varchar(55) DEFAULT NULL, `name2` varchar(55) DEFAULT NULL, `name3` varchar(55) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.00 sec) mysql> ``` > 现在把改表sql改成如下 ``` centos1 root /data/git/myonlineddl >> centos1 root /data/git/myonlineddl >> cat tmp/alter_table.mstest.3307.123456 alter table mstest9 modify name varchar(60) DEFAULT NULL, modify name1 varchar(60) DEFAULT NULL, modify name2 varchar(60) DEFAULT NULL, modify name3 varchar(60) DEFAULT NULL; centos1 root /data/git/myonlineddl >> ``` > 上一个测试用例都将字段长度改成55了,而且将name1从char变成varchar,本次测试将所有字段又扩5个字符长度变成60。按照预期,满足OMM,所以会直接进行alter table操作 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0314/213731_671a634e_1658508.png "clipboard.png") > 可以看到和预期一样。使用啦alter table操作 - (3)测试用例3 - 5.6 > 改表前的表结构 ``` mysql> show create table mstest\G *************************** 1. row *************************** Table: mstest Create Table: CREATE TABLE `mstest` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(12) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> ``` > 现在把改表sql改成如下 ``` centos1 root /data/git/myonlineddl >> cat tmp/alter_table.mstest.3308.123456 alter table mstest modify name varchar(15); centos1 root /data/git/myonlineddl >> ``` > - 计划将varchar 从12扩到15 > - 并且将msrt停掉, 来看看效果 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0314/214235_78a05efa_1658508.png "clipboard.png") > - 可以看到因为版本的问题熬制没有满足OMM,所以还是会用工具进行操作,且因为msrt没有运行,则不会监控磁盘空间。 > - 这时候在执行一次刚才的ddl语句会发生什么呢,请看下图 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0314/220256_959aba42_1658508.png "clipboard.png") > 这是因为第二次再执行就满足OMM了,所以会使用alter table直接进行操作 #### 3、api介绍 > api工作原理就是去修改 dbadb.dbadb_alter_table_repl_time表,实现获取改表进度,控制工单状态(暂停,继续,终止)或者修改其他配置项。 ``` mysql> show create table dbadb_alter_table_repl_time\G *************************** 1. row *************************** Table: dbadb_alter_table_repl_time Create Table: CREATE TABLE `dbadb_alter_table_repl_time` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'pk', `order_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对应改表工单号', `user_mail` varchar(50) DEFAULT '' COMMENT '工单申请人的邮箱地址', `port` int(11) NOT NULL DEFAULT '0' COMMENT 'mysql端口, 表示该端口需要定制化延迟时间, 且检查所有从库', `chunk_size` int(11) DEFAULT '3000' COMMENT '对应ghost命令的--chunk-size=xxx', `run_state` int(11) DEFAULT '0' COMMENT '0正常改表, 1暂停改表, -1终止改表. 改成1, 可以暂停改表, 改成0又可以继续改表. 改成-1终止该工单改表(注意需要修改dbadb工单号对应的那行, 否则不会生效. chunk_size,run_state,repl_time是基于工单号的)', `repl_time` int(11) NOT NULL DEFAULT '60' COMMENT '最大允许多少秒的延迟', `big_table` tinyint(4) DEFAULT '0' COMMENT '是否支持大表改表, 如果表大小超过500g, 需要将这个字段改成1. 修改后仅单次生效', `disk_space` tinyint(4) DEFAULT '0' COMMENT '如果主库磁盘空间不足表大小的两倍不允许改表, 如果需要继续改表需要将这个字段改成1,表示允许【磁盘空间大小=表大小+50G】. 修改后仅单次生效', `osc_tool` tinyint(4) DEFAULT '0' COMMENT '0表示只能选择改表工具, 优先选ghost, 如果置为1. 表示强制使用pt-osc进行改表, 适用于ghost不能用的场景. 修改后仅单次生效', `progress` varchar(50) NOT NULL DEFAULT '0%' COMMENT '改表进度值', `max_connect` int(11) DEFAULT '2500' COMMENT '改表过程中, 连接数超过这个值就会kill掉空连接', `unique_key` tinyint(4) DEFAULT '0' COMMENT '是否支持添加唯一索引, 添加唯一索引有丢数据得风险(目标唯一索引的列存在重复值的话就会丢数据) 1表示允许, 默认是0', `remarks` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', PRIMARY KEY (`id`), UNIQUE KEY `ixk_order_id` (`order_id`), KEY `ixk_port` (`port`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='改表配置表,通过操作这个表动态调整改表状态,以及改表工具的参数' 1 row in set (0.00 sec) mysql> ``` ##### (1)用法介绍 > 总共就四个参数,curl命令的apiurl关键字 需要改成api 的url

- key > 操作动作,可选操作有如下几个动作。需要注意:基于工单的是需要一个工单号,基于端口的是要一个端口。 > - stop_task 终止改表,基于工单的 > - pause_task 暂停改表,基于工单 > - start_task 继续改表,基于工单 > - get_progress 获取改表进度,基于工单 > - big_table 允许超过500g的大表进行改表操作,基于端口 > - disk_space 主库磁盘空间不足表大小的两倍不允许改表,设置这个参数可以允许,基于端口 > - repl_time 从库允许的最大延迟秒数,默认60s,基于工单 > - chunk_size 这个可以忽略,基于工单

- value > 指定一个值,整数。只有当key=repl_time | chunk_size 才有效,其他清空使用这个选项不生效。

- mail > 一个邮箱地址。主要是用于记录操作日志,操作人的邮箱。

- OrderId > 工单号

##### (2)简单用例 ###### 以下基于工单号操作 - API > 获取某工单的改表进度 > - key=get_progress > - mail=1005155691@qq.com > - OrderId=4900579887 ``` #操作命令 curl 'apiurl?key=pause_task&mail=1005155691@qq.com&OrderId=4900579887' ```

> 暂停某工单的改表任务 > - key=pause_task > - mail=1005155691@qq.com > - OrderId=4900579887 > stop_task start_task同这个操作流程 ``` #操作命令 curl 'http://apiurl?key=get_progress&mail=1005155691@qq.com&OrderId=4900579887' ```

> 修改延迟时间 > - key=repl_time 【修改chunk_size同理】 > - value=30 > - mail=1005155691@qq.com > - OrderId=4900579887 ``` #操作命令 curl 'http://apiurl?key=repl_time&value=30&mail=1005155691@qq.com&OrderId=4900649172' ```

###### 以下基于端口号操作 - API > 允许大表改表 > - key=big_table 【修改disk_space同理】 > - mail=1005155691@qq.com > - port=20948 > 注意:除big_table,disk_space,需要修改不存在的行,不能通过api修改 ,需要通过脚本,后文有介绍。 ``` #操作命令 curl 'http://apiurl?key=big_table&mail=1005155691@qq.com&port=20948' ```

###### 以下基于脚本操作 > 修改chunk_size > - -a chunk_size 【修改chunk_size】 > - -N 100 【修改后的值】 > - -P 20002 【mysql端口,大写P】 > - -u 1005155691@qq.com 【用户邮箱地址,建议写】 ``` #操作命令 bash main.sh -a chunk_size -N 100 -P 20002 ```

> 修改延迟时间 > - -a repl_time 【修改repl_time】 > - -N 1 【修改后的值,秒数】 > - -P 20001 【mysql端口,大写P】 > - -u 1005155691@qq.com 【用户邮箱地址,建议写】 ``` #操作命令 bash main.sh -a repl_time -N 10 -P 20001 ```

> 不支持添加唯一索引问题处理 > - key=unique_key > - mail=1005155691@qq.com > - port=3306 > 注意:仅单次生效,变更后,只要该端口有改表工单执行了,这个配置就失效了 ![Image description](https://images.gitee.com/uploads/images/2021/0506/150131_c99649a7_1658508.png "2.png") > 对于上述这种情况,可以跟业务沟通后,如果能承担丢数据的风险就可以放开该端口的添加唯一索引的限制,但是放开动作仅单次生效,即放开动作操作以后仅有一个工单生效,不管这个工单是否成功,放开动作都将失效。 > 放开添加唯一索引的限制操作流程。 ``` #操作命令 bash main.sh -a unique_key -N 1 -P 3306 -u 1005155691@qq.com ``` ![Image description](https://images.gitee.com/uploads/images/2021/0506/150405_bc5db624_1658508.png "1.png") ##### (3)总结 - 操作分两类:基于工单,基于端口。开启工单前都通过端口,开启工单后都通过工单号。 - 以上列举的用例可能并不全面,读者可以举一反三,照葫芦画瓢按需进行操作。 - 通过api操作。除了big_table|disk_space,其余操作只能通过工单号去操作,后续会找时间完善。 - 通过api操作的动作都可以通过脚本实现,反之不行。 - repl_time|chunk_size需要通过端口号操作的话(就是说改表前需要进行配置)就需要使用脚本操作。 - 这个骚操作可能有点绕,可以多看两遍。有需要的可以联系笔者进行咨询。

### 四、写在最后 - 日拱一卒,终有一日成车,就是干! > 感谢阅读!