一、东窗事发
某个版本送测,测试大佬给提了一个缺陷,且听我描述描述:
-
一个学习任务:
-
两个一模一样的学习动态:
- 产品定义:学习任务(生字学习)完成后,会在小程序生成一个动态,再次完成不重复生成
obviously,上边出现的两个动态不符合“罗辑”
二、排查看看
既然出现了两个动态,那就来看看动态的源头是不是生成了两个
1.先看动态生成的触发点
下边为简化版的伪代码
// student_id - learn_type 是唯一索引
val rt = execSql(
"""
INSERT INTO t_learn_state (student_id, learn_type, create_time, update_time)
VALUES ("bc6b5e6979af11e8a10c1c1b0d1c49aa",10,now(),now())
ON DUPLICATE KEY UPDATE update_time = now()
""")
//判断是否首次完成
if (rt == 1) {
//发送完成MQ消息
sendMq("StudyXXXTopic","ResourceFinish","bc6b5e6979af11e8a10c1c1b0d1c49aa finish 10")
}
复制代码
看起来没什么问题,难道是mq重复消费了?
2.看看mq的消息情况
直接看mq后台的消息记录:
可见有两条时间非常接近的mq消息,展开消息后发现内容是一致的,也就是重复生成了消息,而不是重复消费,怎么会这样呢?难道唯一索引没创建?
3.看看表中有多少条记录
only one!
也就是唯一索引是生效的,表中确实只有一条记录
4.难道对 INSERT ON DUPLICATE KEY UPDATE
理解有误?
首先确认了jdbc的链接参数并没有使用useAffectedRows=true
,也就是该sql的返回值是matched
的行数!(后文也是基于此进行的分析)
再经过几番搜索及请教大佬,返回值确实是这样子的:
- 如果是新插入的记录,那么返回值是
1