pt-online-schema-change修改表结构
1 工具原理
pt-online工具主要是为了实现在线修改表结构,避免执行执行造成的锁表时间太长问题。其运行原理是按执行的SQL命令创建新表,把原表的数据同步到新表内,然后删除原表,把新表的表名修改为原表表名。
2 业务背景
大部分表的设计包含json字段,由于json字段不能之间创建索引,导致慢SQL。针对这一问题,目前的解决方案是表内添加不同条件的虚拟列。在虚拟列字段上创建索引。虚拟列分为VIRTUAL和STORED两种格式。其中VIRTUAL类型的列在之前mysql5.x时会引发Taurus的bug。目前环境都是基于mysql8.0,依然建议使用STORED类型虚拟列。STORED类型虚拟列会占用磁盘空间存储数据,所以select类型的SQL会变快,但是写入会变慢。VIRTUAL类型的虚拟列不实际占用磁盘空间,每次查询时会按照定义计算,对查询语句性能提升不明显,同时也不影响插入SQL的性能。
3 使用时注意事项
3.1 命令分--dry-run 和--execte两步
--dry-run不会实际执行
pt-online-schema-change --user=hose_change_ddl --password='xxxx' --host=xxx --port=3306 D=ekb460mix,t=flow_flow_bk09241039 --alter "xxxx" --recursion-method=none --dry-run --print --charset=utf8mb4
--execute会实际执行
pt-online-schema-change --user=hose_change_ddl --password='xxxx' --host=xxx --port=3306 D=ekb460mix,t=flow_flow_bk09241039 --alter "xxxx" --recursion-method=none --execute --print --charset=utf8mb4
3.2 polar数据库执行时 --host后面指定数据库的主节点,不要制定读写节点。
pt内部的某些主从判断的指令和polar代理有兼容性问题。polar的架构有自己特殊性
3.3 --alter 同时添加多个列时,如果表太大可以分开多次添加。
执行会报资源或者表大问题。
3.4 添加虚拟列
3.4.1 执行过程中VIRTUAL字段的虚拟列被截断也没关系
比如code字段本来长度是code varchar(20) ........VIRTUAL类型,在--dry-run命令没有报错,--execute命令后发现被截断了,但是添加列依然成功了。这个报错不影响,因为在查查询时会再生成。
3.5 VIRTUAL改为STORED
3.5.1 不可以直接执行MODIFY,需要先drop,然后add。
示例:
---错误
pt-online-schema-change --user=hose_change_ddl --password='xxxx' --host=10.0.6.43 --port=3306 D=ekb460mix,t=flow_flow_bk09241039 --alter "MODIFY COLUMN code varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin GENERATED ALWAYS AS (json_unquote(json_extract(`$json`, _utf8mb4'$."form"."code"'))) STORED" --recursion-method=none --dry-run --print --charset=utf8mb4
--正确示例
pt-online-schema-change --user=hose_change_ddl --password='xxxx' --host=10.0.6.43 --port=3306 D=ekb460mix,t=flow_flow_bk09241039 --alter "DROP COLUMN code, ADD COLUMN code varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin GENERATED ALWAYS AS (json_unquote(json_extract(`$json`,_utf8mb4'\$."form"."code"'))) STORED" --recursion-method=none --dry-run --print --charset=utf8mb4
3.5.2 已有数据字段的长度必须<=修改后设置的字段长度(code varchar(20) )
示例
code字段定义为code varchar(20) ........VIRTUAL,但数据超长了。
执行结果:
注意:示例中code字段的长度是code varchar(20) ,但是实际数据中长度有40的,当执行execute命令后,显示是成功了,但查看修改后的表结构发现依然是VIRTUAL。
此时需要将code字段的长度定义为超过最大数据长度即可。如
pt-online-schema-change --user=hose_change_ddl --password='xxxx' --host=10.0.6.43 --port=3306 D=ekb460mix,t=flow_flow_bk09241039 --alter "DROP COLUMN code, ADD COLUMN code varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin GENERATED ALWAYS AS (json_unquote(json_extract(`$json`,_utf8mb4'\$."form"."code"'))) STORED" --recursion-method=none --dry-run --print --charset=utf8mb4
再次查看表结构发现已经修改成功。