Überwachung aktiver Abfragen: Verwendung von pg_stat_activity zur Leistungsoptimierung
Verwenden Sie pg_stat_activity, um aktive PostgreSQL-Abfragen, lange Transaktionen, Sperrwartezustände und Sitzungen zu finden, die abgebrochen werden müssen.
Überwachung aktiver Abfragen: Verwendung von pg_stat_activity zur Leistungsoptimierung
Wenn Ihre Datenbank plötzlich langsamer wird, müssen Sie wissen, was PostgreSQL gerade tut. pg_stat_activity zeigt aktive Abfragen, Leerlaufsitzungen, Sperrwartezustände und offene Transaktionen an, sodass Sie eine langsame Abfrage von einer blockierten unterscheiden können.
Verwenden Sie es während Vorfällen, aber halten Sie auch einige gespeicherte Abfragen für Routineprüfungen bereit. Die folgenden Beispiele konzentrieren sich auf PostgreSQL-Systeme, bei denen Sie die Berechtigung haben, die Aktivität für die Sitzungen zu lesen, die Sie überprüfen müssen.
Die Ansicht pg_stat_activity verstehen
pg_stat_activity ist eine dynamische Systemansicht mit einer Zeile für jeden Serverprozess, der mit dem Datenbankcluster verbunden ist. Dazu gehören Client-Backends, Hintergrundarbeiter und Sitzungen, die im Leerlauf sind, aber noch verbunden sind.
Die Überwachung dieser Ansicht ermöglicht es Ihnen, genau zu sehen, was die Datenbank jetzt tut, was sie für das Debuggen plötzlicher Leistungseinbrüche oder die Diagnose von Konfliktsituationen, die für typische Protokolldateien zu flüchtig sind, unschätzbar macht.
Wichtige Spalten für die Leistungsanalyse
Obwohl pg_stat_activity Dutzende von Spalten enthält, sind die folgenden bei der Diagnose von Leistungsproblemen unerlässlich:
| Spaltenname | Beschreibung | Relevanz für die Optimierung |
|---|---|---|
pid |
Prozess-ID des Backends. | Erforderlich zum Abbrechen oder Beenden von Sitzungen. |
datname |
Name der Datenbank, mit der dieses Backend verbunden ist. | Hilft bei der Eingrenzung der Überwachung in Umgebungen mit mehreren Datenbanken. |
usename |
Benutzer, der die Verbindung initiiert hat. | Identifiziert bestimmte Anwendungs- oder Benutzeraktivitäten. |
application_name |
Name der verbindenden Anwendung (falls vom Client festgelegt). | Hervorragend geeignet, um Verbindungen von bestimmten Microservices zu identifizieren. |
state |
Aktueller Aktivitätsstatus (z. B. active, idle, idle in transaction). |
Kernindikator dafür, was das Backend tut. |
query |
Die aktuelle Abfrage oder die letzte Abfrage für Leerlaufsitzungen. Die Sichtbarkeit kann durch Berechtigungen und Einstellungen eingeschränkt sein. | Identifiziert die beteiligte SQL-Anweisung. |
query_start |
Zeitstempel, wann die aktuelle Abfrageausführung begann. | Wird verwendet, um die Abfragedauer zu berechnen. |
wait_event_type & wait_event |
Details darüber, worauf der Prozess wartet (z. B. Sperrerwerb, E/A). | Kritisch für die Diagnose von Konflikten und Blockierungen. |
Praktische Anwendungsfälle für die Überwachung
Die wahre Stärke von pg_stat_activity liegt in der Filterung der Daten, um spezifische Leistungsfragen zu beantworten.
Alle aktiven Abfragen anzeigen
Um nur die Prozesse zu sehen, die derzeit eine Anweisung ausführen (nicht im Leerlauf), filtern Sie die Ansicht nach der Spalte state.
-- Alle derzeit ausgeführten Abfragen anzeigen
SELECT
pid,
usename,
client_addr,
application_name,
now() - query_start AS duration,
query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC;
Langlaufende Abfragen identifizieren
Das Identifizieren von Abfragen, die länger als erwartet laufen, ist oft der erste Schritt bei der Leistungsoptimierung. Diese Abfragen können Ressourcen verbrauchen, E/A-Spitzen verursachen oder Sperren halten.
Um Abfragen zu identifizieren, die länger als einen bestimmten Schwellenwert (z. B. 5 Sekunden) laufen, verwenden Sie die Intervallsubtraktion mit now() und query_start.
-- Abfragen finden, die länger als 5 Sekunden laufen
SELECT
pid,
usename,
datname,
state,
(now() - query_start) AS duration,
query
FROM pg_stat_activity
WHERE state = 'active'
AND (now() - query_start) > interval '5 seconds'
ORDER BY duration DESC;
Verwenden Sie einen Schwellenwert, der zu Ihrer Arbeitslast passt. Eine fünfsekündige Checkout-Abfrage kann in einer OLTP-Anwendung schwerwiegend sein, während eine fünfminütige Berichtsabfrage normal sein kann, wenn sie außerhalb der Geschäftszeiten läuft.
Sitzungen im Leerlauf in Transaktion diagnostizieren
Eine Verbindung, die idle in transaction ist, hat eine Transaktion gestartet, aber nicht festgeschrieben oder zurückgesetzt. Sie wartet darauf, dass der Client den nächsten Befehl sendet. Diese Sitzungen können Sperren halten und alte Zeilenversionen sichtbar halten, was die Bereinigung durch Autovacuum verzögern und zu Tabellenblähungen beitragen kann.
-- Sitzungen finden, die im Leerlauf sind, aber eine offene Transaktion halten
SELECT
pid,
usename,
client_addr,
application_name,
now() - xact_start AS txn_duration,
query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY txn_duration DESC;
Wenn Sie Sitzungen finden, die Transaktionen minuten- oder stundenlang offen halten, überprüfen Sie den Anwendungspfad, der die Transaktion geöffnet hat. Häufige Ursachen sind fehlende Rollback-Behandlung nach einer Ausnahme, eine Verbindung, die vor der Bereinigung an einen Pool zurückgegeben wurde, oder eine interaktive Admin-Sitzung, die offen gelassen wurde.
Sperrkonflikte und Blockierungen analysieren
Wenn eine Abfrage hängt, wartet sie oft auf eine Sperre, die von einem anderen Prozess gehalten wird. Die Ansicht pg_stat_activity in Kombination mit pg_locks ist entscheidend für die Diagnose von Konflikten.
Um Sitzungen zu finden, die derzeit auf eine Ressource (eine Sperre, E/A usw.) warten, sehen Sie sich die Spalte wait_event an. Wenn eine Sitzung blockiert ist, ist ihr wait_event_type oft Lock.
-- Prozesse identifizieren, die derzeit durch eine Sperre blockiert werden
SELECT
a.pid,
a.usename,
a.query_start,
a.query,
a.wait_event,
a.wait_event_type
FROM pg_stat_activity a
WHERE a.state = 'active'
AND a.wait_event IS NOT NULL
ORDER BY a.query_start;
Für eine schnelle Ansicht "wer blockiert wen" bietet PostgreSQL auch pg_blocking_pids().
-- Blockierte Sitzungen und die sie blockierenden Sitzungen anzeigen
SELECT
blocked.pid AS blocked_pid,
blocked.usename AS blocked_user,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.usename AS blocking_user,
blocking.query AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
WHERE blocked.wait_event_type = 'Lock';
Wenn dies eine blockierte Webanfrage zurückgibt, die auf ein langes Admin-Update wartet, kann das Abbrechen der Admin-Abfrage sicherer sein als das Beenden der Anwendungssitzung.
Verwalten problematischer Sitzungen
Sobald eine problematische Abfrage oder Sitzung anhand ihrer Prozess-ID (pid) identifiziert wurde, bietet PostgreSQL zwei Funktionen zur Verwaltung:
Eine Abfrage mit pg_cancel_backend abbrechen
Diese Funktion versucht, die Ausführung einer bestimmten Abfrage ordnungsgemäß zu stoppen. Die Sitzung selbst bleibt verbunden und für zukünftige Abfragen verfügbar.
-- Beispiel: Die auf PID 12345 laufende Abfrage abbrechen
SELECT pg_cancel_backend(12345);
Eine Sitzung mit pg_terminate_backend beenden
Diese Funktion trennt den Backend-Prozess gewaltsam vom Server. Wenn sich die Sitzung mitten in einer Transaktion befand, führt PostgreSQL automatisch ein Rollback der Transaktion durch.
-- Beispiel: Die Sitzung mit PID 54321 gewaltsam beenden
SELECT pg_terminate_backend(54321);
Versuchen Sie zuerst pg_cancel_backend, wenn die Sitzung einfach eine schlechte Abfrage ausführt. Verwenden Sie pg_terminate_backend für Sitzungen, die feststecken, verlassen sind oder eine offene Transaktion halten, die nicht normal bereinigt werden kann. Das Zurücksetzen einer großen Transaktion kann Zeit in Anspruch nehmen und die E/A-Last erhöhen, also tun Sie dies bewusst.
Best Practices für die Überwachung
Aggressiv filtern
Vermeiden Sie SELECT * FROM pg_stat_activity als Ihre Standard-Produktionsgewohnheit. Die Ausgabe ist verrauscht, und der Abfragetext (query) kann sensible Werte preisgeben, wenn Ihre Anwendungen Literale anstelle von Bindeparametern senden. Wählen Sie die Spalten aus, die Sie benötigen, und filtern Sie nach state, datname, application_name oder Dauer.
Tools für die automatisierte Überwachung verwenden
Manuelle Überprüfungen sind während eines Vorfalls nützlich, aber Trends gehören in die Überwachung. Verfolgen Sie aktive Sitzungen, wartende Sitzungen, lange Transaktionen und die Anzahl der idle in transaction in Ihrem PostgreSQL-Dashboard.
Anweisungsprotokollierung konfigurieren
Kombinieren Sie Echtzeitüberwachung mit historischen Daten. Konfigurieren Sie Parameter wie log_min_duration_statement, um Abfragen zu protokollieren, die einen bestimmten Schwellenwert überschreiten, und so Daten für die Analyse bereitzustellen, auch nachdem die Abfrage ausgeführt wurde.
Fazit
Halten Sie drei gespeicherte Überprüfungen bereit: aktive Abfragen, geordnet nach Dauer, Leerlauftransaktionen, geordnet nach Transaktionsalter, und blockierte Sitzungen mit ihren Blockierern. Wenn PostgreSQL sich langsam anfühlt, sagen Ihnen diese Ansichten, ob Sie SQL optimieren, die Transaktionsbehandlung reparieren oder eine blockierende Sitzung bereinigen müssen.