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

MongoDB批量请求下出现重复文档问题求助

问题分析与解决方案:MongoDB并发更新导致重复文档

问题根源

你遇到的是并发竞态条件问题:
短时间内大量请求同时执行时,多个请求会同时通过exists判断(此时目标文档还未被创建),随后各自执行create操作,最终生成重复文档。因为exists和create是两个独立的数据库操作,中间存在时间窗口,并发请求会钻这个空子,破坏数据一致性。

解决方案

1. 创建唯一复合索引(核心保障)

先给likeCollection创建post_id和user_id的唯一复合索引,从数据库层面强制阻止重复文档插入:

// 在MongoDB shell或初始化脚本中执行
db.likeCollection.createIndex({ post_id: 1, user_id: 1 }, { unique: true })

这个索引会确保post_id与user_id的组合唯一,即便并发请求同时尝试插入重复数据,MongoDB会直接抛出唯一键冲突错误,避免重复文档生成。

2. 改造代码为原子操作(消除竞态窗口)

将分步的exists+create/delete改为原子操作,彻底去掉中间的时间窗口:

// 尝试删除匹配的文档
const deletedDoc = await likeCollection.findOneAndDelete({ post_id, user_id });
// 若未找到可删除的文档(即此前不存在),则插入新文档
if (!deletedDoc) {
  try {
    await likeCollection.create({ post_id, user_id });
  } catch (err) {
    // 捕获唯一键冲突错误(处理极端并发下的最后插入竞争)
    if (err.code === 11000) {
      // 可忽略该错误,说明已有其他请求完成了插入操作
    } else {
      throw err;
    }
  }
}

关键说明

  • 唯一索引是数据一致性的最后防线,即便代码层面的原子操作出现极端情况,数据库层面也能阻止重复数据写入。
  • 捕获错误码11000的唯一键冲突,是为了处理极端并发场景:当多个请求同时进入create分支时,只有第一个请求能成功插入,后续请求触发的错误可直接忽略,因为目标数据已经存在。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:12:15