MongoDB 查找和修改排序

6

我在多个并发进程中使用MongoDB中的FindAndModify。集合大小约为300万条记录,只要我不传递排序选项(按索引字段排序),一切都像火箭一样运行。但是,一旦我尝试这样做,就会在日志中生成以下警告:

warning: ClientCursor::yield can't unlock b/c of recursive lock ns: test_db.wengine_queue top: 
{ 
opid: 424210, 
active: true, 
lockType: "write", 
waitingForLock: false, 
secs_running: 0, 
op: "query", 
ns: "test_db", 
query: { 
    findAndModify: "wengine_queue", 
    query: { 
            locked: { $ne: 1 }, 
            rule_completed: { $in: [ "", "0", null ] }, 
            execute_at: { $lt: 1324381363 }, 
            company_id: 23, 
            debug: 0, 
            system_id: "AK/AK1201" 
        }, 
    update: { 
            $set: { locked: 1 } 
        }, 
    sort: { 
            execute_at: -1 
        } 
}, 
client: "127.0.0.1:60873", 
desc: "conn", 
threadId: "0x1541bb000", 
connectionId: 1147, 
numYields: 0 
}

我已经将查询中的所有键进行了索引,这些键如下:

PRIMARY> db.wengine_queue.getIndexes()
[
{
    "v" : 1,
    "key" : {
        "_id" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "_id_"
},  
{
    "v" : 1,
    "key" : {
        "system_id" : 1,
        "company_id" : 1,
        "locked" : 1,
        "rule_completed" : 1,
        "execute_at" : -1,
        "debug" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "system_id_1_company_id_1_locked_1_rule_completed_1_execute_at_-1_debug_1"
},  
{
    "v" : 1,
    "key" : {
        "debug" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "debug_1"
},
{
    "v" : 1,
    "key" : {
        "system_id" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "system_id_1"
},
{
    "v" : 1,
    "key" : {
        "company_id" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "company_id_1"
},
{
    "v" : 1,
    "key" : {
        "locked" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "locked_1"
},
{
    "v" : 1,
    "key" : {
        "rule_completed" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "rule_completed_1"
},
{
    "v" : 1,
    "key" : {
        "execute_at" : -1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "execute_at_-1"
},
{
    "v" : 1,
    "key" : {
        "thread_id" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "thread_id_1"
},
{
    "v" : 1,
    "key" : {
        "rule_id" : 1
    },
    "ns" : "test_db.wengine_queue",
    "name" : "rule_id_1"
}
]

有没有解决这个问题的方法?

这只是一个警告,表示更新无法产生效果。是否有任何实际停止工作的情况,还是您只是担心这个警告?MongoDB/10gen 对于什么应该或不应该被记录为警告有相当不同的看法,因此您最终会发现有很多事情被记录为警告,但实际上可能不应该。 - Remon van Vliet
不,一切都运作正常。但我有些担心这个警告可能会在我的系统被投入生产中(大约五千万文档)时造成的影响。 - clops
这是相对无害的。我会发布一个答案。 - Remon van Vliet
当日志消息填满磁盘时,它并不是无害的。 - bmargulies
2个回答

4

对于那些感兴趣的人 - 我必须创建一个以集合所要排序的关键字结尾的单独索引。


1
MongoDB文档指出"排序列必须是索引中使用的最后一列" - Alexander Azarov
@AlexanderAzarov 看起来它不再显示这个。 - bmargulies

1

当一个操作(例如长时间更新、删除等)希望产生yield(暂停),但由于无法释放所持有的锁而无法这样做时,会引发该警告。

您排序的字段是否已索引?如果没有为其添加索引,可能会消除警告。


是的,正如您从上面的“getIndexes()”结果中看到的那样,该字段已被索引。 - clops
啊对不起。在这种情况下,我认为您只能忍受警告了。再次说明,这只是一个需要产生结果但无法实现的漫长更新的结果。顺便说一下,其中有一两个无用的索引。请注意,索引 {a:1, b:1, c:1} 和 {a:1} 不是有用的,因为前者包含了后者。 - Remon van Vliet
那么您建议我只保留复合索引吗?如果有其他仅使用“C”或“B”和“C”的操作呢? - clops
1
是的,如果你有 {a:1, b:1, c:1},那么 {a:1} 和 {a:1, b:1} 是暗示的。但这不适用于 {b:1},{c:1} 或 {b:1, c:1}。它是从左到右的。 - Remon van Vliet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接