数据库表字段值设置太短导致的现网问题

故事背景

在一个休闲的周末,突然看到工作群里传来信息:智能运维告警报错了几十条,麻烦看看什么原因。我一看是支付网关报错:----com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'data' at row 1。感觉麻烦了,因为前两天刚上了新版本,可能是新版本的改动导致这个问题,还是支付回调流程报的错- -赶紧打开VPN看一下什么原因。

问题分析

打开服务器查看日志,发现告警是在早上6点到6点08分的时间出现,只是支付宝的自动续费流程出现了,普通下单和微信支付都没有出现。再观察一下有没有正常回调给合作方,如果没有的话那就是用户买了会员但是没发权益,会产生客诉。我都准备写程序手动调一下回调接口,后面看到程序在捕捉异常后也有调用HTTP请求通知合作方,业务流程没问题,我也没这么紧张了。

从上面的业务流程图中可以发现,是最后的更新重试参数data存入数据库时报错,新版本的一个改动是回调参数添加了userId,data的值:{"seqno":"xxx","traceno":"xxx",msg:"xxx" .....} 。因为初始版本的回调参数大约只有100+字符左右,所以默认用了255字符串长度,后面回调参数越加越多,255就不够用了。

组合技

奇怪的是之前这个版本测试了挺久也没有发现这个问题,上线之后才暴露出来。后面分析后才发现是要三种情况的组合技同时满足才能触发该问题。

1、由于正向的下单请求还没执行完保存入库,支付宝就开始发起回调,导致订单查询失败,返回支付网关重试,才会写入重试的参数data。为什么会还没保存入库,因为下单请求是执行完HTTP请求之后再入库,如果HTTP请求还没执行完,回调就过来了,就会出现这种情况,只能说支付宝回调速度太快了- -

2、需要是支付宝的自动续费流程,如果是普通下单流程,是返回了预下单地址,这时候肯定是执行入库完了,用户扫码支付后才会支付回调,所以不会出现问题。微信的自动续费支付回调也没有支付宝速度这么快。

3、userId有长有短,如果短的话是刚好250字符左右,长的话就会超出255报错了。

所以是这三个组合技下来导致现网早晨6点的自动续费时间会报数据库插入报错。

修改字段长度

修复上面的bug就是修改字段长度,最关键的是看数据库改动会不会锁表,如果锁表就会影响业务流程。这个之前已经测试过了。分几种情况:

编码utf8:

50改成60 不锁表

50改成70 锁表

255改成1000 不缩表

分界线 256/3 ≈ 85字节,如果跨越了85字符就会锁表

同理 utf8-mb4 256/4 = 64,以64字符为分界线

大改小 锁表

要扫描所有字段是否符合长度

SQL执行:

alter table xxx modify column data varchar(1000);

因为不会锁表,所以可以直接执行。为了防止锁表,准备另外的页面查询正在执行的SQL,把它kill掉

SELECT * FROM information_schema.processlist WHERE command != 'Sleep';

总结

设计数据库字段的时候一定要好好考虑长度问题,问了一下其他朋友,都有试过这种长度设置不够的情况,最好是预留长一点,如果未来业务拓展会导致字段越来越长,就要设置1000长度左右,之前有一个QUA字段也是封装了多个参数,后面也试过报了插入字段太长。

另外支付回调一定要通知到合作方!还好catch里面发送了HTTP请求,不然问题比较严重,虽然合作方也做了兜底逻辑:没收到支付回调会过一段时间调用我们查询接口查询订单是否支付。

相关推荐
snow@li1 分钟前
SpringBoot:核心注解全景梳理 / @xxx 叫“注解”(Annotation)
java·spring
devilnumber6 分钟前
避坑_IDEA 提取方法(Extract Method)工具
java·ide·intellij-idea
鬼手点金19 分钟前
Agent 的学习机制:后训练、上下文学习与外部化学习
java·人工智能·git·学习·自动化·nanogpt
小陈不好吃30 分钟前
equals 与 hashCode 的契约关系:从 HashMap 到 Lombok 注解
java·hashmap·lombok
tianbin91144 分钟前
大模型训练与推理:API中转站在企业AI落地中的隐藏价值
大数据·后端·ai
xiaogai_gai1 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
打工仔折腾 AI1 小时前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战
环境栈笔记2 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
一只小猪妖2 小时前
分布式唯一 性ID生成方法
后端