Wie töte ich (sicher) lange laufende Operationen in MongoDB?

11

Gelegentlich geraten Vorgänge in MongoDB außer Kontrolle und werden möglicherweise Hunderte von Sekunden lang ausgeführt. Dies wirkt sich auf die Leistung aus, bis sie beendet oder abgeschlossen werden.

Wenn das passiert, weiß ich, dass ich zur killOp()Verfügung habe, aber wie kann ich nur gezielte Langzeitoperationen beenden, ohne (zum Beispiel) auch die Langzeitoperationen zu beenden, die an der Replikation beteiligt sind (was gefährlich sein kann)?

Adam C.
quelle

Antworten:

15

Dies kann etwas schwierig sein, aber die Tatsache, dass die MongoDB-Shell im Grunde ein Javascript-Interpreter ist, gibt uns anständige Optionen hinsichtlich der Filterung. Hier ist die Funktion, mit der ich dies erreiche:

// 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);
        }
    }
};

Dies beendet nur Abfragen oberhalb des maxSecsRunningSchwellenwerts und berührt nichts, was gegen die localDatenbank ausgeführt wird, in der sich das oplogLeben befindet (und daher die Datenbank, die an den lang laufenden Replikationsoperationen beteiligt ist. Es ist relativ einfach, der inneren ifBedingung Kriterien hinzuzufügen um Operationen nach Bedarf basierend auf spezifischen Anforderungen genauer auszurichten.

Der Code ist auch als Kern verfügbar (wo ich daran denken werde, ihn fortlaufend zu aktualisieren).

Adam C.
quelle
Ich habe mehrere Skripte für dieses gesehen. Es ist jedoch eine schöne Verbesserung, zu überprüfen, ob der Vorgang für die lokale Datenbank ausgeführt wird.
Joao
Ja - ich habe dies mehrfach herausgegeben und einen Blog-Beitrag mit einem sehr gefährlichen Skript zum Töten von Ops gesehen, also dachte ich, ich würde mir eine schöne und leicht verlinkbare Version geben
Adam C
3
Ich glaube, dies ist ein gefährliches Skript, zumindest wenn Replikate verwendet werden. Das Ausführen db.currentOp()in unserer Sharded-Datenbank gibt Operationen im Namespace "" (auch bekannt als ns: "") zurück, die sehr lange mit einem Desc von "Repl Writer Worker n" (wobei n eine Ganzzahl ist) ausgeführt werden. Ich würde vorschlagen, die Namespaces mit Abfragen, die Sie möglicherweise beenden möchten, in Ihre tatsächlichen Datenbanken aufzunehmen. So etwas wie && (['users', 'analytics'].indexOf(op.ns) != -1)anstelle der !op.ns.startsWithBedingung.
Runamok
Guter Punkt, und es ist durchaus möglich, dass der leere Namespace in neueren Versionen häufiger vorkommt. Ursprünglich wollte ich das Skript auf dem neuesten Stand halten, aber jetzt habe ich MongoDB verlassen, was ich fürchte, ist unwahrscheinlich. Wenn Sie Ihren aktualisierten Code (mit dem Hinweis, dass er für spätere Versionen gilt) hier als Antwort einreichen, werde ich Sie gerne abstimmen :)
Adam C