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

故事背景

在一个休闲的周末,突然看到工作群里传来信息:智能运维告警报错了几十条,麻烦看看什么原因。我一看是支付网关报错:----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请求,不然问题比较严重,虽然合作方也做了兜底逻辑:没收到支付回调会过一段时间调用我们查询接口查询订单是否支付。

相关推荐
艾莉丝努力练剑16 小时前
【Linux线程】Linux系统多线程(四):线程ID及进程地址空间布局,线程封装
java·linux·运维·服务器·c语言·c++·学习
有味道的男人16 小时前
电商效率翻倍:用 Open Claw 对接 1688 接口,快速实现图片选品 + 货源监控
java·开发语言·数据库
海兰16 小时前
【springboot】gradle快速镜像配置
spring boot·笔记·后端
cheems952716 小时前
[SpringMVC] Spring MVC 留言板开发实战
java·spring·mvc
BioRunYiXue16 小时前
AlphaGenome:DeepMind 新作,基因组学迎来 Alpha 时刻
java·linux·运维·网络·数据库·人工智能·eclipse
武超杰16 小时前
SpringBoot 整合 Spring Security 实现权限控制
spring boot·后端·spring
whatever who cares16 小时前
android中,全局管理数据/固定数据要不要放一起?
android·java·开发语言
XMYX-016 小时前
06 - Go 的切片、字典与遍历:从原理到实战
后端·golang
C1829818257516 小时前
AI idea 集成claude code插件
java·ide·intellij-idea
架构师专栏16 小时前
比 MQ 更轻的异步方案:Spring 内置的这个隐藏功能,很多人还不知道
后端