Überwachung der MongoDB-Leistung: Wichtige Befehle und Metriken erklärt

Lernen Sie, die Leistung Ihrer MongoDB proaktiv mit wichtigen Shell-Befehlen zu überwachen. Diese Anleitung beschreibt, wie Sie den Verbindungsstatus mit `db.currentOp()` und `db.serverStatus()` verfolgen, langsame Abfragen mit den Profiling-Befehlen (`db.setProfilingLevel`) analysieren und entscheidende Metriken zur Ressourcennutzung und Indexgesundheit für eine optimale Datenbankabstimmung interpretieren.

Überwachung der MongoDB-Leistung: Wichtige Befehle und Metriken erklärt

Effektives Datenbankmanagement hängt von einer robusten Überwachung ab. Für MongoDB, eine führende NoSQL-Dokumentendatenbank, ist das Verständnis von Leistungsmetriken entscheidend für die Aufrechterhaltung hoher Verfügbarkeit und Reaktionsfähigkeit. Langsame Abfragen, übermäßiger Ressourcenverbrauch oder unerwartete Verbindungsspitzen können die Anwendungsleistung erheblich beeinträchtigen.

Wenn MongoDB langsamer wird, ist die erste nützliche Frage nicht „Ist die Datenbank schlecht?" Sie lautet: „Was macht der Server gerade, und unterscheidet sich das vom Normalzustand?" Die folgenden Befehle verwende ich für eine erste Durchsicht, bevor ich Indizes ändere, Hardware vergrößere oder der Anwendung die Schuld gebe.

Wichtige Überwachungsbefehle in der MongoDB-Shell (mongosh)

Die primäre Schnittstelle zum Ausführen dieser Befehle ist die MongoDB-Shell (mongosh) oder die ältere mongo-Shell. Alle hier gezeigten Befehle werden innerhalb dieser Shell-Umgebung ausgeführt.

1. Aktuelle Verbindungen verstehen: db.currentOp() und db.serverStatus()

Die Überwachung aktiver Verbindungen ist entscheidend, um Verbindungserschöpfung zu verhindern und langlaufende Operationen zu identifizieren, die Ressourcen blockieren könnten.

db.currentOp()

Dieser Befehl gibt Informationen über Operationen zurück, die derzeit in der Datenbank ausgeführt werden. Er ist unverzichtbar, um langsame oder blockierende Abfragen in Echtzeit zu identifizieren.

Anwendungsbeispiel:

Um alle derzeit ausgeführten Operationen anzuzeigen:

db.currentOp()

Um speziell nach Operationen zu suchen, die länger als einen bestimmten Schwellenwert laufen (z. B. Operationen, die länger als 5 Sekunden laufen):

db.currentOp({"secs_running": {$gt: 5}})

Die Ausgabe enthält Details wie op, ns (Namespace), query und secs_running.

db.serverStatus()

Dieser Befehl liefert umfassende Statusinformationen, wobei der Abschnitt connections entscheidend für die Überwachung von Verbindungspooling und -grenzen ist.

Wichtige Metriken in serverStatus (Abschnitt Verbindungen):

  • current: Die Anzahl der aktiven Verbindungen zum Server.
  • available: Die Anzahl der verfügbaren Verbindungen, die hergestellt werden können (basierend auf dem konfigurierten Maximum).
db.serverStatus().connections

2. Abfrageleistung analysieren: db.getProfilingStatus() und db.setProfilingLevel()

MongoDB bietet integrierte Profiling-Tools, die die Ausführungsdetails von Datenbankoperationen protokollieren und es ermöglichen, ressourcenintensive Abfragen zu identifizieren.

Profiling-Stufen

Die Profiling-Stufen legen fest, welche Operationen protokolliert werden:

  • 0 (Aus): Es werden keine Operationen profiliert.
  • 1 (Langsame Operationen): Es werden nur Operationen profiliert, die langsamer als der konfigurierte Schwellenwert (slowms) sind.
  • 2 (Alle Operationen): Alle Operationen werden profiliert, was eine erhebliche Schreiblasterzeugung verursacht und nur kurzzeitig für gezielte Fehlerbehebung verwendet werden sollte.

Status prüfen

Um die aktuelle Profiling-Stufe anzuzeigen:

db.getProfilingStatus()

Stufe festlegen (Beispiel)

Um Profiling nur für langsame Operationen zu aktivieren (Operationen, die 100 Millisekunden überschreiten):

// Setzen Sie slowms auf 100 Millisekunden (Standard ist normalerweise 100)
db.setProfilingLevel(1, { slowms: 100 })

Tipp: Setzen Sie das Profiling immer wieder auf Stufe 0 zurück, nachdem Sie die erforderlichen Informationen gesammelt haben, um Leistungseinbußen durch übermäßige Protokollierung zu vermeiden.

Profilierte langsame Abfragen anzeigen

Profilierte Operationen werden in der Sammlung system.profile innerhalb der spezifischen überwachten Datenbank gespeichert. Um die 10 langsamsten Abfragen der letzten Stunde anzuzeigen:

db.system.profile.find().sort({millis: -1}).limit(10).pretty()

3. Metriken zur Ressourcennutzung

Das Verständnis, wie MongoDB CPU-, Arbeitsspeicher- und E/A-Ressourcen nutzt, ist für Skalierungsentscheidungen unerlässlich.

Speicher- und Speicherplatznutzung: db.serverStatus()

Die Abschnitte globalLock und storageEngine in serverStatus bieten tiefe Einblicke in das Ressourcenmanagement.

Speicherindikatoren:

  • resident: Menge des physischen Arbeitsspeichers, den der Prozess verwendet.
  • virtual: Gesamter virtueller Arbeitsspeicher, der vom Prozess zugewiesen wurde.
db.serverStatus().globalLock

Überwachung von Sperrkonflikten

MongoDB verwendet interne Sperrmechanismen. Die Überwachung von Sperrerwerb und -wartezeiten hilft, Parallelitätsengpässe zu identifizieren.

Wichtige Metriken in globalLock:

  • currentQueue.readers: Anzahl der Leser, die auf eine Sperre warten.
  • currentQueue.writers: Anzahl der Schreiber, die auf eine Sperre warten.
  • totalTime: Gesamtzeit, die für das Warten auf Sperren über alle Operationen hinweg aufgewendet wurde.

Hohe Werte in currentQueue deuten oft darauf hin, dass Indizes fehlen oder dass Schreiboperationen übermäßig lang sind, was dazu führt, dass sich Leser/Schreiber in einer Warteschlange anstellen.

4. Indexnutzung und -gesundheit: db.collection.stats()

Schlecht genutzte oder fehlende Indizes sind die häufigste Ursache für Leistungseinbußen. Der Befehl stats() hilft bei der Analyse der Indexeffizienz.

Wenn er für eine bestimmte Sammlung (z. B. users) ausgeführt wird:

db.users.stats()

Wichtige zu prüfende Metriken:

  • totalIndexSize: Der gesamte von allen Indizes dieser Sammlung belegte Speicherplatz.
  • indexSizes: Eine Aufschlüsselung der Speichernutzung pro Index.
  • Wenn ein Index vorhanden, aber nie für Lesevorgänge verwendet wird, handelt es sich um Overhead, der für eine Entfernung in Betracht gezogen werden sollte.

5. Datenträger-E/A und Durchsatz: db.serverStatus() (Netzwerk und Operationen)

Die Überwachung der Netzwerkaktivität und der Operationsrate gibt einen Einblick in den Datenbankdurchsatz.

Operationsrate (aus opcounters):

opcounters verfolgt die Gesamtzahl der seit dem letzten Serverneustart ausgeführten Operationen, kategorisiert nach Typ:

  • insert, query, update, delete, getmore, command.

Indem Sie Änderungen dieser Zähler im Laufe der Zeit verfolgen (z. B. durch Vergleich zweier aufeinanderfolgender serverStatus-Aufrufe), können Sie den operativen Durchsatz (Operationen pro Sekunde) berechnen.

Beispielvergleich:

  1. Führen Sie db.serverStatus().opcounters zum Zeitpunkt T1 aus.
  2. Führen Sie db.serverStatus().opcounters zum Zeitpunkt T2 aus.
  3. Subtrahieren Sie die T1-Werte von den T2-Werten, um die Gesamtzahl der in diesem Intervall ausgeführten Operationen zu erhalten.

Best Practices für proaktive Überwachung

  • Automatisierung ist der Schlüssel: Sich ausschließlich auf manuelle Shell-Befehle zu verlassen, ist ineffizient. Integrieren Sie die Überwachung mit Tools wie MongoDB Cloud Manager/Ops Manager oder Überwachungslösungen von Drittanbietern, die diese Endpunkte automatisch abfragen.
  • Basislinien festlegen: Führen Sie Befehle aus, wenn das System gesund ist, um eine Leistungsbasislinie zu etablieren. Jede Abweichung von dieser Basislinie rechtfertigt eine sofortige Untersuchung.
  • Fokus auf Latenz: Obwohl Operationszahlen nützlich sind, priorisieren Sie Latenzmetriken (wie die von Profiling-Protokollen gemeldete Zeit) gegenüber dem rohen Durchsatz, wenn Sie Probleme mit der Benutzererfahrung diagnostizieren.
  • Verbindungen häufig prüfen: In stark frequentierten Anwendungen werden Verbindungslimits oft zuerst erreicht. Überwachen Sie db.serverStatus().connections.current im Verhältnis zum konfigurierten Maximum.

Eine praktische Checkliste für den ersten Durchgang

Wenn jemand sagt „MongoDB ist langsam", vermeiden Sie es, direkt zu Indexänderungen zu springen. Beginnen Sie mit einer kurzen Checkliste und notieren Sie, was Sie sehen.

Prüfen Sie, ob der Server mit aktiven Operationen überlastet ist:

db.currentOp({
  active: true,
  secs_running: { $gt: 2 }
});

Einige wenige langlaufende Operationen können für Analyse-Jobs normal sein. Ein großer Haufen von Schreibvorgängen, Sammlungsscans oder blockierten Operationen ist etwas anderes. Suchen Sie nach dem Namespace in ns, dem Operationstyp in op und der Abfrageform. Wenn viele Operationen hinter einem einzigen Update oder Indexaufbau warten, ist die Lösung nicht dieselbe wie bei einem fehlenden Index für eine Leseabfrage.

Prüfen Sie dann die Verbindungen:

db.serverStatus().connections;

Ein schneller Anstieg von current kann bedeuten, dass ein Anwendungs-Verbindungspool falsch konfiguriert wurde, ein Deployment zu viele Worker erstellt hat oder Clients Zeitüberschreitungen haben und sich erneut verbinden. available nahe Null ist ein dringendes Signal, da neue Clients möglicherweise keine Verbindung herstellen können. Die richtige Antwort könnte eine Pool-Anpassung in der App sein, nicht die Erhöhung des Serverlimits.

Überprüfen Sie als Nächstes die Operationszähler zweimal in einem kurzen Abstand:

const a = db.serverStatus().opcounters;
sleep(5000);
const b = db.serverStatus().opcounters;
printjson({
  insertPer5s: b.insert - a.insert,
  queryPer5s: b.query - a.query,
  updatePer5s: b.update - a.update,
  deletePer5s: b.delete - a.delete,
  commandPer5s: b.command - a.command
});

Zähler seit dem Start sind für den langfristigen Kontext nützlich, aber Unterschiede über ein bekanntes Intervall sagen Ihnen, was gerade passiert. Wenn der Befehlsverkehr hoch ist, aber die Abfragen niedrig sind, betrachten Sie möglicherweise Metadatenprüfungen, Überwachungsrauschen oder Treiberverhalten anstelle normaler Lesevorgänge.

Verwenden von explain() vor dem Beschuldigen der Hardware

Die Profiling-Sammlung kann Ihnen sagen, welche Operationen langsam sind. explain() hilft Ihnen zu verstehen, warum eine Abfrage langsam ist, bevor Sie CPU oder Arbeitsspeicher hinzufügen.

db.users.find({ email: "[email protected]" }).explain("executionStats");

Vergleichen Sie in der Ausgabe totalDocsExamined mit nReturned. Wenn MongoDB eine große Anzahl von Dokumenten untersucht, um einen Benutzer zurückzugeben, benötigt die Abfrage wahrscheinlich einen besseren Index oder einen anderen Filter. Wenn totalKeysExamined hoch ist, existiert ein Index, ist aber möglicherweise nicht selektiv genug für das Abfragemuster.

Für eine zusammengesetzte Abfrage ist die Indexreihenfolge wichtig:

db.orders.find({
  accountId: "acct_123",
  status: "open",
  createdAt: { $gte: ISODate("2025-11-01T00:00:00Z") }
}).sort({ createdAt: -1 });

Ein nützlicher Index könnte sein:

db.orders.createIndex({ accountId: 1, status: 1, createdAt: -1 });

Das ist keine universelle Regel. Der beste Index hängt von der Kardinalität, der Sortierreihenfolge und der gesamten Menge der Abfragen ab, die auf die Sammlung zugreifen. Der Punkt ist, die Datenbank dazu zu bringen, Ihnen den Ausführungsplan zu zeigen, anstatt zu raten.

Profiling-Daten lesen, ohne zu überreagieren

Die Profiling-Stufe 2 protokolliert jede Operation und kann auf stark ausgelasteten Systemen Overhead verursachen. Verwenden Sie sie nur für ein kurzes, gezieltes Zeitfenster. Stufe 1 mit einem angemessenen slowms-Schwellenwert ist sicherer, um langsame Operationen zu finden.

db.setProfilingLevel(1, { slowms: 200 });

Nach dem Sammeln von Daten überprüfen Sie die langsamsten Einträge:

db.system.profile.find(
  {},
  {
    ns: 1,
    op: 1,
    millis: 1,
    command: 1,
    keysExamined: 1,
    docsExamined: 1,
    nreturned: 1
  }
).sort({ millis: -1 }).limit(20).pretty();

Eine einzelne langsame Abfrage bedeutet nicht immer einen Produktionsvorfall. Ein geplanter Bericht, ein kalter Cache nach einem Neustart oder eine seltene Wartungsaufgabe können ganz oben auftauchen. Muster sind wichtiger als eine einzelne Stichprobe. Wenn dasselbe Abfragemuster wiederholt auftritt und weit mehr Dokumente untersucht, als es zurückgibt, haben Sie einen echten Optimierungskandidaten.

Überwachung von Replica Sets und Speicherdruck

Bei Replica Sets hängt die Leistung nicht nur vom Primary ab. Ein Secondary, der zurückfällt, kann das Failover-Vertrauen und die Leselast beeinträchtigen, wenn Clients sekundäre Lesevorgänge verwenden.

rs.status();

Achten Sie auf Member, die nicht gesund sind, unerwartete Statusänderungen oder Replikationsverzögerungen, die sich nicht erholen. Die genau akzeptable Verzögerung hängt von der Anwendung ab. Eine Warteschlangen-ähnliche Arbeitslast toleriert möglicherweise eine kleine Verzögerung. Ein Dashboard, das nahezu Echtzeit-Lesevorgänge verspricht, möglicherweise nicht.

Speicherdruck benötigt denselben Kontext. db.serverStatus() kann Speicher-Engine- und WiredTiger-Metriken anzeigen, aber Tools auf Datenträgerebene sind immer noch wichtig. Wenn MongoDB auf langsamen Datenträgern wartet, zeigen Shell-Befehle innerhalb der Datenbank Symptome an, nicht die Ursache. Korrelieren Sie mit Host-Metriken wie Datenträgerlatenz, Dateisystemnutzung, CPU-Steal und Speicherdruck.

Manuelle Prüfungen in Warnmeldungen umwandeln

Manuelle Befehle sind am besten während der Untersuchung. Für den normalen Betrieb wandeln Sie die nützlichen Signale in automatisierte Prüfungen um: Verbindungsnutzung, Replikationszustand, Rate langsamer Abfragen, Datenträgernutzung, Seitenfehler oder Cachedruck, wo verfügbar, und Operationslatenz. Warnen Sie bei anhaltendem Fehlverhalten, nicht bei jedem einminütigen Spike.

Gute Warnmeldungen enthalten Kontext. „MongoDB langsame Abfragen hoch" ist weniger hilfreich als eine Warnmeldung, die die Datenbank, Sammlung, Abfrageform, aktuelle Rate und einen Link zu aktuellen Profilbeispielen oder Dashboard-Panels enthält. Das Ziel ist es, die ersten zehn Minuten des Vorfalls zu verkürzen.

Was man während einer Verlangsamung nicht tun sollte

Vermeiden Sie es, mehrere Änderungen auf einmal vorzunehmen. Das Hinzufügen eines Index, das Erhöhen von Verbindungslimits, das Neustarten der Anwendung und das Ändern der Poolgrößen im selben Vorfall kann das Symptom beseitigen, aber Sie haben keine Ahnung, welche Aktion geholfen hat. Nehmen Sie eine Änderung vor, beobachten Sie die Metrik, die sich verbessern sollte, und machen Sie sich Notizen.

Seien Sie vorsichtig mit killOp. Es kann nützlich sein, wenn eine Operation eindeutig schädlich ist, aber das Abbrechen zufälliger langlaufender Operationen kann das Anwendungsverhalten verschlechtern. Wenn die Operation zu einer Migration, Sicherung, Indexerstellung oder einem Berichtsjob gehört, identifizieren Sie den Eigentümer, bevor Sie sie stoppen, es sei denn, die Datenbank befindet sich bereits in ernsthaften Schwierigkeiten.

Behandeln Sie serverStatus() nicht als eine einzige magische Gesundheitsbewertung. Es ist eine Sammlung von Zählern und Momentaufnahmen. Ein hoher Wert kann auf einem großen, stark ausgelasteten System normal sein, und ein niedriger Wert kann auf einem kleinen, latenzempfindlichen System schlecht sein. Die nützliche Frage ist, ob sich der Wert in einer Weise geändert hat, die mit dem benutzerseitigen Problem übereinstimmt.

Trennen Sie auch Datenbanksymptome von Deployment-Symptomen. Eine neue Version, die die Abfrageform ändert, größere Verbindungspools öffnet oder eine Hintergrundmigration startet, kann MongoDB wie die Ursache aussehen lassen. Vergleichen Sie den Zeitpunkt langsamer Operationen mit Deployments, Jobplänen, Sicherungen und Verkehrsänderungen, bevor Sie eine reine Datenbankkorrektur vornehmen.

Die MongoDB-Überwachung funktioniert am besten, wenn Sie das aktuelle Verhalten mit einer bekannten Basislinie vergleichen. db.currentOp(), db.serverStatus(), Profiling, explain() und Replica-Set-Prüfungen geben Ihnen genügend Beweise, um zu entscheiden, ob das Problem eine Abfrage, ein Index, das Client-Verbindungsverhalten, die Replikation oder der Host unter der Datenbank ist.