WiredTiger应该处理文档级并发。
Mongo .Net驱动程序是否与此锁定机制兼容?
为什么这段代码没有给我正确的结果:
public class MyClass
{
public int Id { get; set; } = 1;
public List<int> Prop { get; set; }
}
public class MyClassRepository : Repository<int, MyClass>
{
public async Task TestUpdate(MyClass document, int val)
{
var filter = Builders<MyClass>.Filter.Eq("_id", document.Id);
var update = Builders<MyClass>.Update.Push(_ => _.Prop, val);
await this.Collection.UpdateOneAsync(filter, update);
}
}
[Fact]
public async Task Test2()
{
var myClass = new MyClass { Prop = new List<int>() };
Parallel.For(
0,
100,
async i =>
{
await this._repository.TestUpdate(myClass, i);
});
var result = await this._repository.Get(1);
result.Prop.Count.Should().Be(100);
}
我在mongo数据库中的文档中并不总是看到100个整数...
有趣的是,当我检查mongo堆栈时,我在mongo集合中仅看到93个对mongo的更新调用和93个整数。因此,我认为驱动程序是问题。
Mongo堆栈:
{
"op" : "update",
"ns" : "auditing.myclasses",
"command" : {
"q" : {
"_id" : NumberInt(1)
},
"u" : {
"$push" : {
"Prop" : NumberInt(42)
}
},
"multi" : false,
"upsert" : false
},
"keysExamined" : NumberInt(1),
"docsExamined" : NumberInt(1),
"nMatched" : NumberInt(1),
"nModified" : NumberInt(1),
"numYield" : NumberInt(0),
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(1),
"w" : NumberLong(1)
}
},
"Database" : {
"acquireCount" : {
"w" : NumberLong(1)
}
},
"Collection" : {
"acquireCount" : {
"w" : NumberLong(1)
}
}
},
"millis" : NumberInt(0),
"planSummary" : "IDHACK",
"execStats" : {
"stage" : "UPDATE",
"nReturned" : NumberInt(0),
"executionTimeMillisEstimate" : NumberInt(0),
"works" : NumberInt(2),
"advanced" : NumberInt(0),
"needTime" : NumberInt(1),
"needYield" : NumberInt(0),
"saveState" : NumberInt(0),
"restoreState" : NumberInt(0),
"isEOF" : NumberInt(1),
"invalidates" : NumberInt(0),
"nMatched" : NumberInt(1),
"nWouldModify" : NumberInt(1),
"nInvalidateSkips" : NumberInt(0),
"wouldInsert" : false,
"fastmodinsert" : false,
"inputStage" : {
"stage" : "IDHACK",
"nReturned" : NumberInt(1),
"executionTimeMillisEstimate" : NumberInt(0),
"works" : NumberInt(1),
"advanced" : NumberInt(1),
"needTime" : NumberInt(0),
"needYield" : NumberInt(0),
"saveState" : NumberInt(1),
"restoreState" : NumberInt(1),
"isEOF" : NumberInt(1),
"invalidates" : NumberInt(0),
"keysExamined" : NumberInt(1),
"docsExamined" : NumberInt(1)
}
},
"ts" : ISODate("2019-04-12T11:46:59.118+0000"),
"client" : "127.0.0.1",
"appName" : "Auditing",
"allUsers" : [
],
"user" : ""
}
答案 0 :(得分:0)
好吧,我终于明白了这一点。问题完全与c#有关,并且来自在Parallel.For块中使用async / await语法。
将代码替换为下面的代码即可解决此问题。
[Fact]
public async Task Test2()
{
var myClass = new MyClass { Prop = new List<int>() };
var tasks = new List<Task>();
for (var i = 0; i < 100; i++)
{
tasks.Add(this._repository.TestUpdate(myClass, i));
}
await Task.WhenAll(tasks);
var result = await this._repository.Get(1);
result.Prop.Count.Should().Be(100);
}
使我得出这个结论的原因是,注释Get and assert部分导致根本没有在Mongo中插入任何数据。
有关此的更多信息,请参见 Nesting await in Parallel.ForEach
感谢调查此事的人士,不便之处,敬请谅解。