A.A
A.A

Reputation: 4101

Mongodb retryable-writes

If I enable retryable-writes in mongodb and perform the following insert

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

Is it possible that in some circumstances , The driver inserted two same records?

Upvotes: 1

Views: 2314

Answers (1)

kevinadi
kevinadi

Reputation: 13775

Retryable writes are intended to provide "once and only once" semantics for supported storage engines and retryable operations, with specific prerequisites. There are many safeguards intended to prevent retryable writes to happen more than once.

Having said that, in the Retryable Writes documentation page:

If the client application becomes temporarily unresponsive for more than the localLogicalSessionTimeoutMinutes after issuing a write operation, there is a chance that when the client applications starts responding (without a restart), the write operation may be retried and applied again.

This requires a perfect storm of bad luck to occur at exactly the right time, in exactly the right order, spanning more than 30 minutes, for retryable writes to happen twice:

  1. The client sends a retryable write request to the server.
  2. The server applies the write, but a problem prevents the acknowledgement from reaching the client.
  3. The client application hangs for more than localLogicalSessionTimeoutMinutes (default is 30 minutes).
  4. After more than 30 minutes, the application tries to pick up where it left off, thinks that it hasn't receive the acknowledgement for the write, and retries the write.

For this to happen:

  • The application hang must occur at exactly the window of time where:
    • The write occurred in the server.
    • The acknowledgement must not reach the client e.g. lost.
  • The application can pick up where it left off after more than 30 minutes without errors.

This is an extremely unlikely chain of events.

However, if you're worried that you can hit this series of unfortunate events, you can:

  • Insert the document with a specific _id. The second insert will fail since _id must be unique within a collection.
  • Use idempotent operations for updates, such as $set instead of $inc.

Upvotes: 6

Related Questions