Mongodb 可重试写入

Web*_*ter 1 mongodb

如果我在 mongodb 中启用可重试写入并执行以下插入

await db.collection('inventory').insertOne({
  item: 'canvas',
  qty: 100,
  tags: ['cotton'],
  size: { h: 28, w: 35.5, uom: 'cm' }
});
Run Code Online (Sandbox Code Playgroud)

是否有可能在某些情况下,驱动程序插入了两条相同的记录

kev*_*adi 6

可重试写入旨在为受支持的存储引擎和可重试操作提供“一次且仅一次”语义,并具有特定的先决条件。有许多保护措施旨在防止可重试写入不止一次发生。

话虽如此,在Retryable Writes 文档页面中

如果客户端应用程序在发出写入操作后暂时无响应超过 localLogicalSessionTimeoutMinutes,则当客户端应用程序开始响应(无需重新启动)时,可能会重试并再次应用写入操作。

这需要一场完美的厄运风暴在正确的时间以正确的顺序发生,持续超过 30 分钟,以便可重试的写入发生两次:

  1. 客户端向服务器发送一个可重试的写请求。
  2. 服务器应用写入,但出现问题阻止确认到达客户端。
  3. 客户端应用程序挂起超过localLogicalSessionTimeoutMinutes(默认为 30 分钟)。
  4. 30 多分钟后,应用程序尝试从中断的地方继续,认为它没有收到写入的确认,并重试写入。

要做到这一点:

  • 应用程序挂起必须恰好发生在以下时间窗口:
    • 写入发生在服务器中。
    • 确认不得到达客户端,例如丢失。
  • 应用程序可以在超过 30 分钟后从停止的地方继续运行而不会出错。

这是一个极不可能发生的事件链。

但是,如果您担心会遇到这一系列不幸事件,您可以:

  • 插入带有特定_id. 第二次插入将失败,因为_id在集合中必须是唯一的。
  • 使用幂等操作进行更新,例如$set代替$inc.