Comment puis-je (en toute sécurité) tuer les opérations de longue durée dans MongoDB?

11

Parfois, les opérations deviennent incontrôlables dans MongoDB et peuvent finir par s'exécuter pendant des centaines de secondes, et affecter les performances jusqu'à ce qu'elles soient tuées ou terminées.

Lorsque cela se produit, je sais que j'ai killOp()à ma disposition, mais comment puis-je tuer uniquement les opérations de longue durée ciblées sans également tuer (par exemple) les opérations de longue durée impliquées dans la réplication (ce qui peut être dangereux)?

Adam C
la source

Réponses:

15

Cela peut être un peu délicat, mais le fait que le shell MongoDB soit fondamentalement un interpréteur Javascript nous donne des options décentes en termes de filtrage. Voici la fonction que j'utilise pour y parvenir:

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

Cela ne tuera que les requêtes au-dessus du maxSecsRunningseuil et ne touchera rien qui s'exécute contre la localbase de données, où se trouve la oplogvie (et donc la base de données impliquée dans les opérations de réplication à long terme. Il est relativement facile d'ajouter des critères au ifconditionnel interne pour cibler plus précisément les opérations selon les besoins en fonction des besoins spécifiques.

Le code est également disponible en tant qu'essentiel (où je me souviendrai de le mettre à jour régulièrement).

Adam C
la source
J'ai vu plusieurs scripts pour celui-ci. Néanmoins, vérifier si l'opération s'exécute sur la base de données locale est une belle amélioration.
joao
ouais - je l'ai donné à plusieurs reprises, et j'ai vu un article de blog avec un script très dangereux pour tuer des ops, alors j'ai pensé me donner une version agréable et facilement reliable
Adam C
3
Je crois que c'est un script dangereux au moins lors de l'utilisation de jeux de réplicas. L'exécution db.currentOp()sur notre base de données fragmentée renvoie des opérations dans l'espace de noms "" (alias ns: "") qui sont très longues avec une desc de "repl writer worker n" (où n est un entier). Je suggérerais de mettre en liste blanche les espaces de noms dans vos bases de données réelles avec des requêtes que vous voudrez peut-être tuer. Quelque chose comme && (['users', 'analytics'].indexOf(op.ns) != -1)au lieu de la !op.ns.startsWithcondition.
runamok
Bon point, et il est tout à fait possible que l'espace de noms vide se produise plus fréquemment dans les versions plus récentes - j'avais initialement l'intention de maintenir le script à jour, mais j'ai maintenant quitté MongoDB, il est donc peu probable que j'en ai peur. Si vous soumettez votre code mis à jour (avec une note qu'il s'applique aux versions ultérieures) ici comme réponse, je serai ravi de vous voter :)
Adam C