2

(updated on 2019-7-2) 7 days after, finally, I solved this question. Well, my code is OK, WTF, wasted so much time. The question is my team use AliCloud(a chinese company, like Amazon, Azure), and the Mongodb has many versions, We created the DataBase a year ago, and that version, will lock the database while processing a trunsaction.

if you have some problem, hope my experence could help.


forgive my poor english...

dev enviroment : mongodb4.0 cluster with 3nodes, support transactions. .net core 2.2 (mongodb driver 2.7.2+) Robot 3T(mongod tool)

the MongoDB database will be locked 60 seconds after starting a transaction, I thought maybe the problem is lock level, but I've already tried all enums of readconcern or writeconvern, nothing helps.

here is an image: now database is locked, I cannot query data in Robot 3T, neither my web app.

I mean, before commitTransaction/abortTransaction, the database will be locked. if the transcation is a big one, complete in 30s, actually the webapp cannot read data response to other visitors.

in fact, the users of my webapp always say, why your app runs so slow (because every transcation lock the database for 0.xx second)

enter image description here

TransactionOptions option = new TransactionOptions(readConcern: ReadConcern.Snapshot,writeConcern: WriteConcern.W1);
ClientSessionOptions so =new ClientSessionOptions();
so.DefaultTransactionOptions = option;

var session = _dataBase.Client.StartSession();
var products = _dataBase.GetCollection<Product>("products"); 
var TV = new Product { Description = "Television", SKU = 4001, Price = 2000 };  
session.StartTransaction(option);

try
    { 
      products.InsertOne(session, TV); 
      // after the sentence , database will be locked 

// before commitTransaction, the webapp cannot response, like Robot 3T, // looks like the database is locked
session.CommitTransaction();
Nick.Jane
  • 31
  • 5
  • I'm not a MongoDB expert, but shouldn't you need to call `session.CommitTransaction();` or any other method to close transaction? – vasily.sib Jun 24 '19 at 03:33
  • @vasily.sib , of course, I will commitTransaction. I mean, before commitTransaction, the database will be locked. if the transcation is a big one, complete in 30s, actually the webapp cannot read data response to other visitors – Nick.Jane Jun 24 '19 at 03:41
  • I can't see it in your code. Do you **always** commit or rollback your transaction? What if exception is thrown? – vasily.sib Jun 24 '19 at 03:45
  • 1
    What do you do for a transaction to last up to 30s ?? – Fildor Jun 24 '19 at 06:24
  • well, the point is not 30s(just a example), transaction locks the database for 0.1S,then the other requests have to wait. in Sql Server, it is a RowData Lock, why mongodb locks the whole database. @Fildor – Nick.Jane Jun 24 '19 at 07:25
  • 1
    _"in Sql Server, it is a RowData Lock,"_ There is no "Row" in MongoDB that would be comparable. My suspicion is that there is something between `products.InsertOne(session, TV); ` and `session.CommitTransaction();` that is causing this. – Fildor Jun 24 '19 at 12:26

1 Answers1

0

i tried to reproduce the kind of locking you're talking about with the following code. but i could not see any locking with transactions in my local environment, which uses the v2.8.1 driver and mongodb server v4.0.6. could you possibly run the following code in your environment and report back the output? also note the code uses my library MongoDB.Entities so please install that with nuget first.

using MongoDB.Entities;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace StackOverflow
{
    public class Program
    {
        public class Product : Entity
        {
            public string Description { get; set; }
            public double Price { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test-transacion-locking", "localhost", 27017);

            (new Product {
                Description = "television",
                Price = 399 }
            ).Save();

            Task.Run(() =>
            {
                using (var TN = new Transaction())
                {
                    var sw1 = new Stopwatch(); sw1.Start();

                    Console.WriteLine("transaction started...");

                    TN.Update<Product>()
                      .Match(p => p.Price == 399)
                      .Modify(p => p.Price, 499)
                      .Modify(p => p.Description, "updated television")
                      .Execute();

                    TN.Save(new Product { Description = "radio", Price = 199 }); ;

                    Task.Delay(10000).Wait(); //wait 10 seconds before commiting

                    TN.Commit();

                    Console.WriteLine($"transaction took: {sw1.Elapsed.TotalSeconds} seconds");
                }
            });

            Task.Delay(10).Wait(); //wait 10 millis to let the transaction begin first

            var sw2 = new Stopwatch(); sw2.Start();

            Console.WriteLine("tv count query started...");

            var tvCount = DB.Queryable<Product>()
                            .Where(p => p.Description.Contains("television"))
                            .Count();

            Console.WriteLine($"found {tvCount} televisions in {sw2.Elapsed.TotalSeconds} seconds");

            Console.ReadKey();
        }
    }
}

this is my output:

transaction started...
tv count query started...
found 1 televisions in 0.0986646 seconds
transaction took: 10.1092237 seconds
Dĵ ΝιΓΞΗΛψΚ
  • 5,068
  • 3
  • 13
  • 26
  • thanks a lot, your code is awesome, I solve my problem. The world will be more beautiful because of you! – Nick.Jane Jul 02 '19 at 01:57
  • @Nick.Jane you are most welcome. so what was the cause behind your locking issue? – Dĵ ΝιΓΞΗΛψΚ Jul 02 '19 at 03:03
  • my team use AliCloud(a chinese company, like Amazon, Azure), and the Mongodb has many versions(they are all V4.0 above, like 4.01, 4.02, 4.03), We created the DataBase a year ago, and that version, will lock the database while processing a trunsaction. I asked them to update the version to the latest and fix the problem. @Ryan Gunner – Nick.Jane Jul 05 '19 at 02:08