Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-43889

Distinguish between a retryable write and a transaction when failing a command

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.2.6, 4.3.4, 4.0.19
    • Component/s: None

      Description

      Currently, most txnNumber errors refer only to transactions, even if the error pertains to a retryable write. This can create a poor user experience for someone who is only using retryable writes.

      We should audit these types of errors on the server and determine whether the command was a part of a retryable write or a transaction. Depending on the answer, we can return one of the following errors:

      "Cannot start transaction X on session <UUID> because a newer transaction or retryable write with txnNumber Y has already started on this session."

      "Retryable write with txnNumber X is prohibited on session <UUID> because a newer transaction or retryable write with txnNumber Y has already started on this session."

      ORIGINAL POST:

      Code that reproduces the issue:

              private static async Task TestSingleSession(MongoClient client)
              {
                  var col = client.GetDatabase("_test").GetCollection<BsonDocument>("concurrent");                        
                  using (var session = await client.StartSessionAsync())
                  {
                      var ops = Enumerable.Range(0, 100)
                          .Select(async e =>
                          {
                              await col.ReplaceOneAsync(session, Builders<BsonDocument>.Filter.Eq("_id", e),
                                  new BsonDocument
                                  {
                                      { "_id", e },
                                      { "data", $"someData_{e}" },
                                  },
                                  new UpdateOptions { IsUpsert = true });
                          })
                          .ToArray();
                      await Task.WhenAll(ops);
                  }
              }
      

       

      When running above code I'm getting the exception:

      MongoCommandException: Command update failed: Cannot start transaction 1 on session c4fd4081-e0f0-40d6-84fc-cdfeccc74e3b - hf9LJrhq2lfp667gnURrBVE7MCUS1NJZYDmWlqfKWl0= because a newer transaction 3 has already started..

      This is misleading as there's no explicit transaction in progress.

      I know now that we should use either

      • ReplaceOneAsync overload without¬†session
      • Create new session per call to ReplaceOneAsync with session

       

      background: I've encountered that issue in production code where one method is being used with and without transaction - our solution was to simply create a intermediate overloaded method that creates a session for you and passes it into method that accepts the session.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              ali.mir Ali Mir
              Reporter:
              marek.kresnicki@gmail.com Marek Kresnicki
              Participants:
              Votes:
              0 Vote for this issue
              Watchers:
              15 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: