Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-3301

Multi-thread Transaction Failure for Sharded Cluster

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Works as Designed
    • Affects Version/s: 2.11.5
    • Fix Version/s: None
    • Component/s: Transactions
    • Security Level: Public
    • Labels:
      None
    • Environment:
      MongoDB Sharded Cluster version: 4.2.2-ent
      OS: Ubuntu 16.04

      Description

      5 threads to execute transactions in parallel and encounter lots of 251 errors:

      MongoCommandException, 251, "NoSuchTransaction", "Command insert failed: cannot continue txnId 35 for session 618e6cd1-4db1-40ea-8b22-6386e204c36b - xxx with txnId 36"

       

      Reproduce code:

      public class TransactionTest
      {
          private const string DatabaseName = "PressureTest";
          private const string CollectionName = "Test";
          public const string ConnectionString = "";
          public MongoClient GetMongoClient(int timeout = 5)
          {
              var clientSettings = MongoClientSettings.FromConnectionString(ConnectionString);
              clientSettings.ConnectTimeout = TimeSpan.FromSeconds(5);
              clientSettings.ServerSelectionTimeout = TimeSpan.FromSeconds(timeout);
              clientSettings.AllowInsecureTls = true;
              var mongoClient = new MongoClient(clientSettings);
              return mongoClient;
          }
       
          public async Task TestTransactionAsync()
          {
              var client = GetMongoClient();
              var tasks = new List<Task>();
              for (int i = 0; i < 5; ++i)
              {
                  //var client = GetMongoClient(i + 5);
                  tasks.Add(DoAsync(client));
              }
              await Task.WhenAll(tasks);
          }
       
          private async Task DoAsync(IMongoClient mongoClient)
          {
              Console.WriteLine("Client hashcode: " + mongoClient.GetHashCode());
              var collection = mongoClient.GetDatabase(DatabaseName).GetCollection<BsonDocument>(CollectionName);
       
              while (true)
              {
                  var uuid1 = Guid.NewGuid().ToString("N").Substring(24);
                  var uuid2 = Guid.NewGuid().ToString("N").Substring(24);
                  try
                  {
                      using (var session = await mongoClient.StartSessionAsync())
                      {
                          session.StartTransaction();
                          await collection.InsertOneAsync(session, new BsonDocument("Uuid", uuid1));
                          await collection.InsertOneAsync(session, new BsonDocument("Uuid", uuid2));
       
                          await session.CommitTransactionAsync();
                      }
                      Console.WriteLine($"[{uuid1}] [{uuid2}]");
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("$$$ " + e.Message);
                  }
              }
          }
      }
      

       

      If change the thread to 1, no error happens.

       

      If not reuse the mongoClient by changing TestTransactionAsync(): create a dedicated mongoClient for each thread, no error happens:

      public async Task TestTransactionAsync()
      {
          var tasks = new List<Task>();
          for (int i = 0; i < 5; ++i)
          {
              var client = GetMongoClient(i + 5);
              tasks.Add(DoAsync(client));
          }
          await Task.WhenAll(tasks);
      }
      

      The above modification intentionally passes different ServerSelectionTimeout value to prevent mongoclient from reusing. Refer to: https://mongodb.github.io/mongo-csharp-driver/2.11/reference/driver/connecting/#mongo-client

      multiple MongoClient instances created with the same settings will utilize the same connection pools underneath.

      The document suggests re-use mongoclient by store it in a global place. However, a singleton mongoclient leads to parallel transaction failure.

        Attachments

          Activity

            People

            Assignee:
            dmitry.lukyanov Dmitry Lukyanov
            Reporter:
            finiskygarden@gmail.com fini sky
            Participants:
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: