「这是我参与11月更文挑战的第32天,活动详情查看:2021最后一次更文挑战」。
原创不易,望多多关注、多多点赞🙇👍
事故描述
公司的app客户端会上报一些用户数据到Java后台服务,其中有一个点击时间
的字段。今天在巡查日志的时候,发现了大量该保存该字段是的error日志。
如下:
Data truncation: Incorrect datetime value: ‘53884-04-07 04:09:44’ for column ‘clickTime’ at row 1
伪代码
1 | java复制代码/** |
猜想
根据异常日志和源代码,我们猜想可能是因为有些客户端没有按原定的以秒
为单位来上报,而是使用的毫秒
为单位。
为了验证猜想,决定写个main
方法验证一下。
现场还原
1 | java复制代码public static void main(String[] args) { |
结果和预想的一样,果然是因为毫秒的问题。
解决问题
1 | java复制代码String time = user.getClickTime(); |
你以为这样就结束了吗?
修复好发生产后,却爆发了更多的异常,量级是原来的十多倍,我一下子慌了神,赶紧找运维大佬回滚版本。
这次的异常日志如下:
Data truncation: Incorrect datetime value: ‘0’ for column ‘clickTime’ at row 1
Data truncation: Incorrect datetime value: ‘1’ for column ‘clickTime’ at row 1
原来客户端还上报了数量庞大的 0 和 1。
当该字段长度不为10或13时,程序中是不做任何处理,直接插入到数据库的,数据库表结构中该字段为 datetime
类型的,所以当保存 0 或 1 时会报错。
那我们之前将 0 或 1, 转换后保存的究竟时什么呢? 再次通过 main
方法模拟一下:
1 | java复制代码public static void main(String[] args) { |
发现,原来 SimpleDateFormat
的 format()
方法会对所有数字类型都进行格式化,这一点大家一定要注意了。
这次是真的解决了
把代码继续兼容优化:
1 | java复制代码String time = user.getClickTime(); |
同时和客户端的同事沟通,统一时间单位。
本文转载自: 掘金