Jak (bezpiecznie) zabić długotrwałe operacje w MongoDB?

11

Czasami operacje wymykają się spod kontroli w MongoDB i mogą działać przez setki sekund i wpływać na wydajność, dopóki nie zostaną zabite lub zakończone.

Kiedy tak się dzieje, wiem, że mam killOp()do dyspozycji, ale jak mogę zabijać tylko ukierunkowane operacje długotrwałe bez zabijania (na przykład) operacji długotrwałych związanych z replikacją (co może być niebezpieczne)?

Adam C.
źródło

Odpowiedzi:

15

Może to być trochę trudne, ale fakt, że powłoka MongoDB jest w zasadzie tłumaczem JavaScript, daje nam przyzwoite opcje filtrowania. Oto funkcja, której używam do osiągnięcia tego:

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

Spowoduje to tylko zabicie zapytań powyżej maxSecsRunningprogu i nie dotknie niczego, co działa na localbazie danych, czyli tam, gdzie oplogżyje (i stąd jest baza danych, która jest zaangażowana w długo działające operacje replikacji. Stosunkowo łatwo jest dodać kryteria do ifwarunku wewnętrznego w celu dokładniejszego ukierunkowania operacji w zależności od potrzeb na podstawie konkretnych potrzeb.

Kod jest również dostępny jako lista (gdzie będę pamiętać, aby aktualizować go na bieżąco).

Adam C.
źródło
Widziałem kilka skryptów do tego. Niemniej jednak sprawdzenie, czy operacja jest wykonywana w lokalnej bazie danych, jest dobrym ulepszeniem.
joao
tak - rozdawałem to wiele razy i widziałem post na blogu z bardzo niebezpiecznym skryptem do zabijania operacji, więc pomyślałem, że dam sobie przyjemną i łatwą do połączenia wersję
Adam C
3
Uważam, że jest to niebezpieczny skrypt przynajmniej podczas korzystania z replikaz. Uruchamianie db.currentOp()na naszej podzielonej bazie danych zwraca operacje w przestrzeni nazw „” (aka ns: „”), które działają bardzo długo z opisem „pracownika zapisującego replikę n” (gdzie n jest liczbą całkowitą). Sugeruję dodanie białej listy obszarów nazw do rzeczywistych baz danych za pomocą zapytań, które możesz chcieć zabić. Coś jak && (['users', 'analytics'].indexOf(op.ns) != -1)zamiast !op.ns.startsWithwarunku.
runamok,
Dobra uwaga i jest całkiem możliwe, że pusta przestrzeń nazw występuje częściej w nowszych wersjach - pierwotnie zamierzałem aktualizować skrypt, ale teraz opuściłem MongoDB, więc obawiam się, że jest mało prawdopodobne. Jeśli prześlesz zaktualizowany kod (z uwagą, że dotyczy on późniejszych wersji) tutaj jako odpowiedź, chętnie cię zagłosuję :)
Adam C