异步MongoDB的并发变化(c#)
本文关键字:变化 并发 MongoDB 异步 | 更新日期: 2023-09-27 18:06:02
假设我有一个简单的对象:
class A
{
int _id;
int V1;
int V2;
}
和MongoDB表与一堆这些:
现在,我定义了两个异步更新操作:void UpdateV1(int id, int V)
{
var F = Builders<A>.Filter.Eq(_ => _._id, Id);
var U = Builders<A>.Update.Set(_ => _.V1, V);
Mongo.Driver.UpdateOneAsync(F, U);
}
void UpdateV2(int id, int V)
{
var F = Builders<A>.Filter.Eq(_ => _._id, Id);
var U = Builders<A>.Update.Set(_ => _.V2, V);
Mongo.Driver.UpdateOneAsync(F, U);
}
如果我运行以下命令:
UpdateV1(1, 10);
和
UpdateV2(1, 20);
在不同的线程上,但大致同时,发生了什么?
我得到:
- 只有V1或V2改变的记录?
- V1和V2都改变的记录?
我问这个问题的原因是我们有一个非常奇怪的错误,看起来第一个选项是正在发生的事情,但预期的结果显然是最后一个。
当我们做阻塞调用时,这些问题开始消失,但这也可能是一个副作用。
这是使用c#驱动程序,一切都是最新版本。
我认为这不是你的查询问题,因为mongodb保证原子性和并发控制,看看这个链接了解更多。
我怀疑你的问题来自于如何安排任务。看看这个例子,如果您不等待Parallel.Invoke
中的结果,您的查询将不会被执行,因为进程将在执行任务之前退出。所以如果你添加Console.ReadLine()
,你的进程将被阻塞,允许mongo运行任务
namespace ConsoleApplication1
{
class Program
{
static MongoClient mongoClient = new MongoClient();
static IMongoDatabase databaseBase = mongoClient.GetDatabase("dbTest", null);
static IMongoCollection<A> collection = databaseBase.GetCollection<A>("tests", null);
static void Main(string[] args)
{
var a = new A
{
_id = 1,
V1 = 0,
V2 = 0
};
Parallel.Invoke( ()=> { var res=UpdateV1(1, 10).Result; }, ()=> { var res = UpdateV2(1, 20).Result; });
//Console.ReadLine();
}
static async Task<long> UpdateV1(int id, int V)
{
var F = Builders<A>.Filter.Eq(a => a._id, id);
var U = Builders<A>.Update.Set(a => a.V1, V);
var result = await collection.UpdateOneAsync(F, U);
return result.ModifiedCount;
}
static async Task<long> UpdateV2(int id, int V)
{
var F = Builders<A>.Filter.Eq(_ => _._id, id);
var U = Builders<A>.Update.Set(_ => _.V2, V);
var result = await collection.UpdateOneAsync(F, U);
return result.ModifiedCount;
}
}
class A
{
public int _id;
public int V1;
public int V2;
}
}
也许你只能用UpdateOne
代替UpdateOneAsync
,看看会发生什么?