【问题标题】:MongoDB: phantom records in $unwind results under heavy loadMongoDB:重负载下 $unwind 结果中的幻像记录
【发布时间】:2014-07-10 04:12:14
【问题描述】:

我有一个像这样的简单元素集合

{_id: n, xs: [...]}    

我正在尝试计算所有数组中的元素总数

db.testRace.aggregate([{ $unwind : "$xs" }, { $group : { _id : null, count : { $sum : 1 } } }])

除非我开始对这个集合进行大量更新,否则它会很好用。在繁重的更新操作负载下,我得到了错误的总数 - 比它应该的略大。

它可以很容易地复制。 首先生成一些测试数据

for(var i = 1; i <= 1000000; i++) {
    db.testRace.insert({_id: i, xs: [i]});
}

然后模拟很多更新

while(true) {
    var id = Math.floor((Math.random() * 1000000) + 1);
    var obj = db.testRace.find({_id: id}).next();
    obj.some="change";
    db.testRace.update({_id: id}, obj);
}

当它运行时,做聚合展开查询。 没有负载我得到正确的结果 - 1000000。但是当有很多更新时,我得到更大的数字,比如 1001456。

如果我像这样运行查询

db.testRace.aggregate([{ $unwind : "$xs" }, {$group: {_id:"$xs", count:{$sum: 1}}}, { $sort : { count : -1 } }, { $limit : 2 }]);

我明白了

"result" : [
    {
        "_id" : 996972,
        "count" : 2
    },
    {
        "_id" : 997789,
        "count" : 2
    }
],

所以似乎对某些记录进行了两次聚合计数。

这是预期的行为还是我做错了聚合?

我在本地 mongodb 实例上进行了测试,版本 - 2.4.9

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    由于 MongoDB 处理读取隔离的方式,这是预期的行为。当您有一个长时间运行的查询(并且读取每个文档的聚合是一个长时间运行的查询)并在查询期间更新该数据时,它可能会影响查询中是否返回更新的数据 - 取决于何时发生的情况,您可能会错过、收到或收到两次文档。

    来自源代码:

    在收益期间插入、删除或修改的任何数据都应该被 查询返回的查询可能会或可能不会被该查询返回。这 查询可能返回:没有;之前的数据;之后的数据;或两者 之前的数据和之后的数据。

    简而言之,查询和查询之间没有隔离 插入/删除/更新。又名,READ_UNCOMMITTED。

    https://github.com/mongodb/mongo/blob/master/src/mongo/db/exec/plan_stage.h

    您的聚合查询正在产生中间查询,在此期间会更新一些数据。这会影响查询结果。

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 2020-05-08
      • 2019-04-25
      • 2010-09-09
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多