mongodb4.0 запустить транзакцию в c # (диск версии 2.7+), во время транзакции вся база данных будет заблокирована, как это исправить? - PullRequest
2 голосов
/ 24 июня 2019

(обновлено 2019-7-2) Через 7 дней, наконец, я решил этот вопрос.Ну, мой код в порядке, WTF, потратил так много времени.Вопрос заключается в том, что моя команда использует AliCloud (китайская компания, такая как Amazon, Azure), и Mongodb имеет много версий. Мы создали базу данных год назад, и эта версия заблокирует базу данных во время обработки транзакции.

если у вас возникнут проблемы, надеюсь, что мой опыт может помочь.


простите мой плохой английский ...

dev среда: кластер mongodb4.0 с 3 узлами,поддержка транзакций..net core 2.2 (драйвер mongodb 2.7.2+) Robot 3T (инструмент mongod)

база данных MongoDB будет заблокирована через 60 секунд после начала транзакции, я подумал, что, возможно, проблема в уровне блокировки, но яуже перепробовал все перечисления readconcern или writeconvern, ничего не помогает.

вот изображение: теперь база данных заблокирована, я не могу запрашивать данные ни в Robot 3T, ни в моем веб-приложении.

Я имею в виду,перед commitTransaction / abortTransaction база данных будет заблокирована.если перевод большой, завершается через 30 с, на самом деле веб-приложение не может прочитать ответ данных другим посетителям.

на самом деле, пользователи моего веб-приложения всегда говорят, почему ваше приложение работает так медленно (потому что каждый перевод блокирует базу данных на 0.xx секунды)

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();

1 Ответ

0 голосов
/ 25 июня 2019

Я попытался воспроизвести вид блокировки, о котором вы говорите, с помощью следующего кода.но я не мог видеть блокировку транзакций в моей локальной среде, которая использует драйвер v2.8.1 и сервер mongodb v4.0.6.Не могли бы вы запустить следующий код в вашей среде и сообщить результат?также обратите внимание, что код использует мою библиотеку MongoDB.Entities , поэтому, пожалуйста, сначала установите ее с nuget.

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();
        }
    }
}

это мой вывод:

transaction started...
tv count query started...
found 1 televisions in 0.0986646 seconds
transaction took: 10.1092237 seconds
...