mongodb 4.0 在c#(驱动版本2.7+)中启动一个事务,在事务期间,整个数据库将被锁定,如何解决?
mongodb4.0 start a transaction in c# (drive rversion 2.7+), in the duration of transaction, the whole database will be locked, how to fix it?
(更新于2019-7-2)7天后,我终于解决了这个问题。
好吧,我的代码还可以,WTF,浪费了这么多时间。
问题是我的团队使用阿里云(一家中国公司,如亚马逊、Azure),Mongodb 有很多版本,我们一年前创建了数据库,那个版本在处理截断时会锁定数据库。
如果你有什么问题,希望我的经验能帮到你。
原谅我糟糕的英语...
开发环境:
mongodb4.0集群3节点,支持事务。
.net 核心 2.2(mongodb 驱动程序 2.7.2+)
机器人3T(mongod工具)
MongoDB 数据库将在开始事务后 60 秒后被锁定,
我想也许问题是锁级别,
但我已经尝试了 readconcern 或 writeconvern 的所有枚举,没有任何帮助。
这是一张图片:现在数据库已锁定,我无法在 Robot 3T 中查询数据,我的 Web 应用程序也无法查询。
我的意思是,在commitTransaction/abortTransaction之前,数据库将被锁定。如果交易很大,30秒内完成,实际上webapp无法读取其他访问者的数据响应。
事实上,我的 webapp 的用户总是说,为什么你的应用程序运行这么慢(因为每个事务都将数据库锁定 0.xx 秒)
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();
我试图用以下代码重现您所说的那种锁定。但是我在本地环境中看不到任何事务锁定,它使用 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 Whosebug
{
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
(更新于2019-7-2)7天后,我终于解决了这个问题。 好吧,我的代码还可以,WTF,浪费了这么多时间。 问题是我的团队使用阿里云(一家中国公司,如亚马逊、Azure),Mongodb 有很多版本,我们一年前创建了数据库,那个版本在处理截断时会锁定数据库。
如果你有什么问题,希望我的经验能帮到你。
原谅我糟糕的英语...
开发环境: mongodb4.0集群3节点,支持事务。 .net 核心 2.2(mongodb 驱动程序 2.7.2+) 机器人3T(mongod工具)
MongoDB 数据库将在开始事务后 60 秒后被锁定, 我想也许问题是锁级别, 但我已经尝试了 readconcern 或 writeconvern 的所有枚举,没有任何帮助。
这是一张图片:现在数据库已锁定,我无法在 Robot 3T 中查询数据,我的 Web 应用程序也无法查询。
我的意思是,在commitTransaction/abortTransaction之前,数据库将被锁定。如果交易很大,30秒内完成,实际上webapp无法读取其他访问者的数据响应。
事实上,我的 webapp 的用户总是说,为什么你的应用程序运行这么慢(因为每个事务都将数据库锁定 0.xx 秒)
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();
我试图用以下代码重现您所说的那种锁定。但是我在本地环境中看不到任何事务锁定,它使用 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 Whosebug
{
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