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

故事背景

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

相关推荐
卷无止境3 分钟前
Polars 多 DataFrame 合并操作全指南
后端
祀爱7 分钟前
定时任务之BackgroundService的详细教程
后端·c#·asp.net
超梦dasgg8 分钟前
Sentinel生产环境实战全解
java·微服务·sentinel
青云计划11 分钟前
MySQL技术文档
java·mysql
qq_25183645712 分钟前
基于java 汽车检修管理系统设计与实现 论文
java·开发语言·汽车
量子炒饭大师16 分钟前
【Linux系统编程】Cyberpunk在霓虹丛林中构建堡垒 ——【基础开发工具(1)】一文带你初步了解 软件包管理器 并 快速上手 yum和apt 工具
java·linux·运维·apt·yum·软件包管理器
E等于MC平方19 分钟前
用 Rust 写一个工业级 POSP 支付系统
后端·rust·消费·8583·交易·posp·银联
Finger#0000FF21 分钟前
从零上手VibeCoding(ClaudeCode+DeepSeek V4.Pro)
java·人工智能·ai编程·vibe coding·claudecode
木子墨51621 分钟前
系统设计面试 | 实现一个限流器:滑动窗口 → 令牌桶 → 漏桶
java·开发语言·数据结构·数据库·面试·职场和发展
吴声子夜歌33 分钟前
Java——synchronized
java·synchronized