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

Ada*_*m C 11 replication mongodb

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

发生这种情况时,我知道我可以killOp()使用,但是如何仅终止有针对性的长时间运行的操作而不终止(例如)复制中涉及的长时间运行的操作(这可能很危险)?

Ada*_*m C 16

这可能有点棘手,但事实上 MongoDB shell 基本上是一个 Javascript 解释器,在过滤方面为我们提供了不错的选择。这是我用来完成此操作的函数:

// 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);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

这只会终止高于maxSecsRunning阈值的查询,并且不会触及针对local数据库运行的任何内容,这是存在的oplog地方(因此是涉及长时间运行的复制操作的数据库。向内部if条件添加条件相对容易根据特定需求,根据需要更精确地定位操作。

该代码也可用作要点(我会记得不断更新它)。

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