一、背景
上周承接了一个新需求需要为券打标签,此处不关注业务背景,只聚于技术业务流程:上游服务通过Kafka下发标识,我们服务订阅kafka,kafka消费后对分片库(采用mycat实现分库,目前有128个分片,通过user_id作为分片路由键)中的xx表tag字段(新增字段:tag)进行更新。在周四正式发版之前,周三晚上通过onlineDDL完成对分片库加字段。
二、现象1、周四晚上
周四晚上10点切完流量一会后,异常日志告警就出来了:
这个是老代码根本没动过,去年也出现过这个相同的这个问题,当时只出现了一会大概3分钟后就消失了(联系运维观察估计是网络抖动造成的),于是决定进一步观察。
后续又陆续出现告警:Got packets out of order,Communications link failure,立马联系DBA检查分片库,得到的回复是数据库目前都正常,无异常。后续连这个分片库的服务也开始告警,立马进一步向上级leader请示。经商讨后:决定将连接这个分片库所有服务串行重启。晚上流量相对较少,后面偶尔报一次。
2、周五
第二天早上9点随着流量增加告警频繁出现,游走在UIOC事件的边缘,非常危险,立即拉mycat中间件维护人员、DBA等人员一起分析。将当前版本的改动:新增字段和更新sql语句发给中间件相关同事(目前Kafka每批最多消费20条数据,于是决定采用批量更新的方式提升效率)。
经分析未找到出现问题的原因,无奈之下准备回退版本(不再消费kafka,让kafka先积压,同时不再读取),并于13:00发布到生产,发布完后无告警。
在生产回滚后继续分析,大家都怀疑是批量更新导致的问题,于是准备晚上尝试验证一下:新增单个更新sql,通过动态开关走批量更新单个更新。
晚上先打开kafka消费开关,开启单条更新sql开关,更新tag和读取tag都正常,无告警,至此实锤是因Mycat批量更新导致的问题。
三、问题分析1、rewriteBatchedStatements
先明确jdbc驱动(5.1.13版本以上才生效)中rewriteBatchedStatements含义,重写批量sql比如update语句:update t set … where id = 1; update t set … where id = 2; update t set … where id = 3,会将多条语句组成一条语句提交给mysql。
2、mycat为什么不支持
上github上查看有没有类似问题,在mycat源码中的issues直接输入关键字rewriteBatchedStatements:
可以看到在2020年6月17合入以下分支:https//MyCATApache/Mycat-Server/tree/Mycat-server-1.6.76-test,以下是mycat版本发布时间线:
查看当前使用的版本未1.5.1,当然不支持批量重写后的update语句,进而导致乱包,mycat出现乱序进一步影响这分片库的其他业务。
四、解决及总结
基于以上分析得出结论:mycat版本较低无法支持批量update,提交批量update语句致Mycat乱报,进而引发一系列问题。针对以上问题,给出以下解决方案:
1、规避业务写批量更新语句;
2、中间件升级mycat版本,但目前有很多定制化开发,中间件不是太愿意升级。
3、换成其他中间件比如shardingjdbc;
短期按方案1执行,目前分片库存量数据量达到将近百亿,明年逐步完成去Mycat。