如何(安全地)终止MongoDB中长期运行的操作?


11

有时,操作会在MongoDB中失控,最终可能会运行数百秒,并影响性能,直到操作被终止或完成。

发生这种情况时,我知道我killOp()有空,但是我如何只杀死目标的长时间运行的操作而又不杀死(例如)复制中涉及的长时间运行的操作(这很危险)?

Answers:


15

这可能有点棘手,但是MongoDB shell基本上是Java解释器这一事实为我们提供了过滤方面的不错选择。这是我用来完成此任务的功能:

// kills long running ops in MongoDB (taking seconds as an arg to define "long")
// attempts to be a bit safer than killing all by excluding replication related operations
// and only targeting queries as opposed to commands etc.
killLongRunningOps = function(maxSecsRunning) {
    currOp = db.currentOp();
    for (oper in currOp.inprog) {
        op = currOp.inprog[oper-0];
        if (op.secs_running > maxSecsRunning && op.op == "query" && !op.ns.startsWith("local")) {
            print("Killing opId: " + op.opid
            + " running over for secs: "
            + op.secs_running);
            db.killOp(op.opid);
        }
    }
};

这只会杀死超过maxSecsRunning阈值的查询,并且不会碰到任何针对local数据库运行的查询,因为数据库是存在的oplog地方(因此是长期运行复制操作所涉及的数据库。将条件添加到内部if条件数据库相对容易根据特定需求更精确地定位所需的操作。

该代码也可以作为要点使用(我会记得在此不断进行更新)。


我已经看过几个脚本。但是,检查操作是否针对本地数据库运行是一个不错的改进。
joao 2014年

是的-我已经给出了很多次,并且看到了一篇博客文章,其中包含一个非常危险的脚本来杀死操作人员,所以以为我会给自己一个很好的且易于链接的版本
Adam C

3
我认为至少在使用副本集时,这是一个危险的脚本。db.currentOp()在我们的分片数据库上运行会返回“”命名空间(aka ns:“”)中的操作,这些操作使用“ repl writer worker n”(其中n是整数)的desc会运行很长时间。我建议您使用可能要杀死的查询将名称空间列入您的实际数据库白名单。喜欢的东西&& (['users', 'analytics'].indexOf(op.ns) != -1),而不是!op.ns.startsWith条件。
runamok

好点,在新版本中,空白名称空间很有可能会更频繁地发生-我本来打算使脚本保持最新状态,但是我现在离开了MongoDB,所以恐怕不太可能。如果您在此处提交更新的代码(并注意它适用于更高版本)作为答案,我会很乐意为您投票:)
Adam C
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.