You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+MyBatis更新MySQL偶发主键重复Duplicate entry报错原因

报错原因分析

这个错误本质是竞态条件导致的并发问题,你的逻辑在单线程场景下运行没有问题,但多线程并发请求时会出现漏洞,具体原因如下:

  • 你当前的「先查询匹配记录→不存在则插入」是两个独立的非原子操作,没有任何并发控制。如果两个携带完全相同业务参数的请求同时进入该方法,同一时间执行完selectByExample,都得到空的查询结果,就会同时触发插入操作,触发主键冲突。
  • 另一个常见诱因:MyBatis执行插入操作后,会将数据库生成的自增主键回写到你传入的score实体对象中。如果这个score对象被复用(比如没有重新new新对象,直接修改字段后再次调用该方法),下次插入时就会携带已经存在的主键值,直接触发主键重复报错。
  • 补充排查点:如果你的主键不是数据库自增,而是代码层面生成(比如雪花算法、自定义生成逻辑),生成规则存在并发安全问题也会导致重复ID。
解决方案
  • 最推荐的方案:直接使用MySQL原生的INSERT ... ON DUPLICATE KEY UPDATE原子语法实现upsert,你只需要给gameId、userId、targetUserId、voteRound这几个业务唯一字段加上联合唯一索引,数据库会自动判断是插入还是更新,完全避免竞态问题。
  • 如果要保留现有代码逻辑:可以给整个方法加分布式锁,锁key用四个业务字段拼接而成,同一时间只有一个同参数的请求能执行该逻辑;或者给查询语句加排他锁(select ... for update),同时开启事务控制,避免两个请求同时拿到空查询结果。
  • 检查实体对象复用逻辑:每次调用插入操作时确保传入的是新实例化的SparkGameUserScore对象,或者插入完成后手动清空实体的主键字段。

内容的提问来源于stack exchange,提问作者Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 22:09:02