PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Konfigurieren von PostgreSQL für Observability

PostgreSQL verfügt über eine Fülle von Konfigurationsoptionen, aber das Ändern der Standardeinstellungen einiger dieser Optionen verbessert die Beobachtbarkeit Ihres PostgreSQL-Servers drastisch. Sie sollten diese Optionen festlegen und konfigurieren, bevor Probleme in der Produktion auftreten, da sie wichtige Informationen zum Verständnis und zur Lösung dieser Probleme liefern können.

Lesen Sie weiter, um mehr über die Einstellungen und Erweiterungen zu erfahren, die Metriken und Informationen über das Innenleben Ihres PostgreSQL-Servers offenlegen.

Protokollzeilenpräfix

Das log_line_prefix Die Konfigurationsoption bestimmt, was PostgreSQL am Anfang jeder Protokollzeile schreibt. Die Standardeinstellung hängt von der spezifischen Linux-Distribution oder verwalteten Lösung ab, die Sie verwenden, aber meistens enthält sie einige Elemente nicht, die sich als sehr nützlich erweisen können, um sich schlecht benehmende Clients aufzuspüren. Probieren Sie dieses log_line_prefix aus :

log_line_prefix = '%m [%p] %a %u %d %h '

Es enthält den Zeitstempel (%m ), die PID des Backend-Prozesses (%p ), der Anwendungsname (%a ) des Clients, den Benutzernamen, mit dem sich der Client verbunden hat (%u ), die Datenbank, mit der sich der Client verbunden hat (%d ) und den Hostnamen oder die IP-Adresse, von der die Verbindung kommt (%h ). Dies führt zu Protokollzeilen wie dieser:

2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 ERROR:  relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 STATEMENT:  select * from pgbench_akkounts;

die viel nützlicher sind als die Standardeinstellung. Sie können sehen, dass sich ein Client über 172.17.0.1 verbunden hat als Benutzer postgres zur Datenbank bench , und die Anwendung war psql . Definitiv eine Verbesserung gegenüber der Standardoption, die nur Folgendes anzeigt:

2021-01-30 05:13:22.630 UTC [63] ERROR:  relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:13:22.630 UTC [63] STATEMENT:  select * from pgbench_akkounts;

Langsame Abfragen protokollieren

PostgreSQL kann so konfiguriert werden, dass Abfragen protokolliert werden, deren Ausführung länger als eine festgelegte Zeitspanne dauert. Diese gehen in dieselbe Protokolldatei; es gibt keine separate Protokolldatei für langsame Abfragen wie in MySQL.

Um Anweisungen zu protokollieren, deren Ausführung länger als 1 Sekunde dauert, verwenden Sie das log_min_duration_statement Option wie folgt:

log_min_duration_statement = 1s

Beachten Sie, dass log_min_duration_statement berücksichtigt alle Anweisungen (einschließlich beispielsweise lang andauernder Admin-Anweisungen wie REINDEX TABLE ) und nicht nur Abfragen (SELECT ). Hier sind einige Protokolleinträge, die von dieser Option erzeugt werden:

2021-01-30 08:42:57.473 UTC [62] psql postgres postgres 172.17.0.1 LOG:  duration: 1016.283 ms  statement: select pg_sleep(1);
2021-01-30 08:52:00.541 UTC [62] psql postgres postgres 172.17.0.1 LOG:  duration: 1118.277 ms  statement: select pg_sleep(1.1);

Wenn dies zu zu vielen Protokollen ähnlicher Aussagen führt, können Sie Postgres anweisen, nur einen Prozentsatz davon zu protokollieren, indem Sie Folgendes verwenden:

log_min_duration_statement = -1
log_min_duration_sample = 1s
log_statement_sample_rate = 0.25

Dadurch werden nur 25 % der Anweisungen protokolliert, die protokolliert werden können (diejenigen, deren Ausführung länger als 1 Sekunde dauerte). Die Protokollausgabe ist die gleiche wie zuvor. Es gibt keine Möglichkeit festzustellen, wie viele zulässige Anweisungen nicht protokolliert wurden.

Um alle Anweisungen zusammen mit der für ihre Ausführung benötigten Zeit zu protokollieren, verwenden Sie log_statement Option stattdessen:

log_statement = mod
log_duration = on

Die Option „mod“ weist Postgres an, DDLs und datenmodifizierende Anweisungen zu protokollieren. Dies führt zu Protokollen wie diesen:

2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG:  statement: insert into pgbench_tellers(tid,bid,tbalance) values (10,1,0)
2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG:  duration: 0.241 ms

Seien Sie gewarnt, dass dies nicht der Fall ist Es ist möglich, die auf diese Weise aktivierte Anweisungsprotokollierung zu testen, alle Anweisungen werden protokolliert, und Sie erhalten am Ende Tonnen von Protokolleinträgen.

Protokollierung von Sperren und Deadlocks

Abfragen können zu lange warten, um eine Sperre zu erhalten. Typischerweise wird mit der Option lock_timeout eine Obergrenze für die Wartezeit festgelegt , normalerweise auf der Clientseite. Wenn eine Abfrage so lange darauf gewartet hat, eine Sperre zu erhalten, bricht Postgres die Ausführung dieser Abfrage ab und protokolliert einen Fehler:

2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 ERROR:  canceling statement due to lock timeout
2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 STATEMENT:  cluster t;

Angenommen, Sie möchten ein Sperrzeitlimit von 1 Minute festlegen, aber Abfragen protokollieren, die länger als beispielsweise 30 Sekunden auf Sperren warten. Sie können dies tun mit:

log_lock_waits = on
deadlock_timeout = 30s

Dadurch werden Protokolle wie diese erstellt:

2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 LOG:  process 70 still waiting for ShareLock on transaction 493 after 30009.004 ms
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 DETAIL:  Process holding the lock: 68. Wait queue: 70.
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t for update;

Die Verwendung von deadlock_timeout ist kein Tippfehler:Es ist der Wert, den der Lock-Waitlogging-Mechanismus verwendet. Idealerweise sollte so etwas wie log_min_duration_lock_wait stehen ,aber leider ist das nicht der Fall.

Bei tatsächlichen Deadlocks bricht Postgres die Deadlock-Transaktionen nach deadlock_timeout ab Dauer und protokolliert die anstößigen Aussagen. Es ist keine explizite Konfiguration erforderlich.

2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 LOG:  process 68 detected deadlock while waiting for ShareLock on transaction 496 after 30007.633 ms
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 DETAIL:  Process holding the lock: 70. Wait queue: .
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t where a=4 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 ERROR:  deadlock detected
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 DETAIL:  Process 68 waits for ShareLock on transaction 496; blocked by process 70.
        Process 70 waits for ShareLock on transaction 495; blocked by process 68.
        Process 68: select * from t where a=4 for update;
        Process 70: select * from t where a=0 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 HINT:  See server log for query details.
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t where a=4 for update;

Selbstbereinigungen protokollieren

Der Autovacuum-Prozess setzt ein, wenn Postgres feststellt, dass sich die Daten in einer Tabelle ausreichend geändert haben, um ein Vakuum und eine Analyse zu rechtfertigen. Um diesen Vorgang im Auge zu behalten, aktivieren Sie die Protokollierung von Autovacuum-Läufen:

log_autovacuum_min_duration = 250ms

Hier ist ein Beispieleintrag, der durch übermäßige Änderungen an einer Tabelle verursacht wurde:

2021-01-30 10:23:33.201 UTC [63]     LOG:  automatic vacuum of table "postgres.public.t": index scans: 0
        pages: 0 removed, 95 remain, 0 skipped due to pins, 0 skipped frozen
        tuples: 8991 removed, 10000 remain, 0 are dead but not yet removable, oldest xmin: 492
        buffer usage: 215 hits, 4 misses, 4 dirtied
        avg read rate: 1.885 MB/s, avg write rate: 1.885 MB/s
        system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s
        WAL usage: 244 records, 1 full page images, 67984 bytes
2021-01-30 10:23:33.222 UTC [63]     LOG:  automatic analyze of table "postgres.public.t" system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s

Beachten Sie, dass das Autovakuum normalerweise nach dem Vakuum eine Analyse auslöst, die ebenfalls protokolliert wird.

Diese Protokolle helfen Ihnen herauszufinden, wie Sie die Autovacuum-Parameter am besten einstellen können, und helfen bei der Untersuchung, ob und wann das Autovacuum nicht so effektiv ist, wie Sie es sich vorgestellt haben.

Protokollierungsprüfpunkte

Checkpointing ist der Prozess, bei dem WAL-protokollierte Änderungen in die eigentlichen Dateien verschoben werden, die Tabellen unterstützen. Idealerweise sollten Prüfpunkte in regelmäßigen und nicht zu häufigen Intervallen auftreten, da es sich um einen CPU- und Festplatten-intensiven Prozess handelt. Aus verschiedenen Gründen werden Checkpoints auch vor der nächsten geplanten Zeit durchgeführt, was zu einer verringerten Abfrageleistung führt.

Aktivieren Sie die Protokollierung von Checkpoints, um die Checkpoint-Häufigkeit und -Effizienz im Auge zu behalten:

log_checkpoints = on

Dies weist PostgreSQL an, Folgendes zu protokollieren, wenn ein Prüfpunkt auftritt:

2021-01-30 10:05:57.085 UTC [56]     LOG:  checkpoint starting: immediate force wait
2021-01-30 10:05:57.159 UTC [56]     LOG:  checkpoint complete: wrote 0 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.000 s, sync=0.000 s, total=0.074 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=0 kB

Die erste Zeile enthält die Flags, die das Backend an den Checkpointer übergeben hat. Sie können sehen, dass die „Erzwingung“ einen Checkpoint verursacht hat, obwohl es keine ausstehenden Änderungen am Checkpoint gab. Wenn „immediate“ nicht angegeben worden wäre, hätte der Checkpointer bis zu checkpoint_completion_target gecheckt .

Andere serverseitige Einstellungen

Es gibt ein paar andere Einstellungen, die Sie in Ihrer PostgreSQL-Konfiguration aktivieren können, die bei der Diagnose von Problemen helfen:

  • track_io_timing - Setzen Sie dies auf on lässt Sie die Zeit sehen, die indisk I/O für jede Abfrage verbracht wird (kombiniert mit der unten beschriebenen Erweiterung pg_stat_statements). Sehen Sie sich die Dokumentation zu einem Vorbehalt an, um dies zu aktivieren, sollte aber auf fast jedem modernen Linux sicher sein. Es ist unmöglich, die Festplatten-E/A-Kosten einer Abfrage zu sehen, ohne dies zu aktivieren.
  • track_commit_timestamp - Setzen Sie dies auf on kann beim Debuggen von Replikationsverzögerungen und anderen replikationsbezogenen Problemen hilfreich sein.

Statistiken über pg_stat_statements abfragen

Die Erweiterung pg_stat_statements ist ein unverzichtbares Zubehör für jede PostgreSQL-Bereitstellung. Es sammelt und zeichnet Statistiken für jede ausgeführte Abfrage auf und präsentiert sie als Ansicht namens „pg_stat_statements“. Dies ist eine Erweiterung, was bedeutet, dass Sie sie explizit in jeder Datenbank installieren müssen, für die Sie Daten benötigen, indem Sie den Befehl verwenden:

CREATE EXTENSION pg_stat_statements;

Da die Erweiterung auf eine .so angewiesen ist , müssen Sie diese mit shared_preload_libraries laden :

shared_preload_libraries = 'pg_stat_statements'

Dies erfordert leider einen Neustart des PostgreSQL-Servers; Stellen Sie also sicher, dass Sie dies tun, bevor Sie live gehen.

Wenn Sie von einer früheren Version von PostgreSQL aktualisiert haben, stellen Sie sicher, dass Sie auch Ihre pg_stat_statement-Erweiterung aktualisieren, indem Sie Folgendes verwenden:

ALTER EXTENSION pg_stat_statements UPDATE;

Die Erweiterung pg_stat_statements protokolliert nichts, sie wird über die Abfrage der gleichnamigen Ansicht verwendet. Weitere Einzelheiten finden Sie in der offiziellen Dokumentation.

Ausführungspläne abfragen über auto_explain

auto_explain ist eine weitere Erweiterung, die im Kern von PostgreSQL vorhanden ist. Es kann die Ausführungspläne von langsamen Abfragen protokollieren. Es muss nur zu shared_preload_libraries hinzugefügt werden , und muss nicht als Erweiterung installiert werden. Es hat auch ein paar andere Optionen, die normalerweise auf Nicht-Standardwerte gesetzt werden müssen:

shared_preload_libraries = 'pg_stat_statements,auto_explain'

auto_explain.log_min_duration = 1s
auto_explain.log_analyze = on
auto_explain.log_buffers = on
auto_explain.log_triggers = on
auto_explain.log_timing = on
auto_explain.log_verbose = on
auto_explain.log_format = json

Oben wird der Ausführungsplan für alle Abfragen protokolliert, deren Ausführung länger als 1 Sekunde dauert. Hier ist eine Beispielausgabe:

2021-01-30 11:28:25.977 UTC [64] psql postgres postgres 172.17.0.1 LOG:  duration: 1.305 ms  plan:
        {
          "Query Text": "SELECT n.nspname as \"Schema\",\n  c.relname as \"Name\",\n  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' TH
EN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'table' WHEN 'I' THEN 'index' END as \"Type\",\n  pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\nFROM pg_catalog.pg_class c
\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\nWHERE c.relkind IN ('r','p','v','m','S','f','')\n      AND n.nspname <> 'pg_catalog'\n      AND n.nspname <> 'information_schema'\n      AND
n.nspname !~ '^pg_toast'\n  AND pg_catalog.pg_table_is_visible(c.oid)\nORDER BY 1,2;",
          "Plan": {
            "Node Type": "Sort",
            "Parallel Aware": false,
            "Startup Cost": 32.93,
            "Total Cost": 33.01,
            "Plan Rows": 32,
            "Plan Width": 224,
            "Actual Startup Time": 1.292,
            "Actual Total Time": 1.298,
            "Actual Rows": 0,
[... lots of text snipped ...]

Weitere Informationen zu auto_explain finden Sie in der offiziellen Dokumentation.

Die Erweiterungen pg_stat_statements und auto_explain sind die einzigen zwei weithin unterstützten Optionen, die PostgreSQL für das Abfrageleistungsmanagement und das Abfrageplanmanagement bietet. Es lohnt sich, diese beiden Funktionen kennenzulernen und im Voraus zu planen, sie in der Produktion einzusetzen.

Anwendungsname

Der Anwendungsname ist ein clientseitiger Parameter und kann normalerweise in DSNs oder Verbindungszeichenfolgen im libpq-Stil festgelegt werden, die Ihre Anwendung für Verbindungsinformationen verwendet. Viele Tools und Dienstprogramme im PostgreSQL-Ökosystem verstehen den Anwendungsnamen, und es ist hilfreich, diesen auf einen aussagekräftigen Wert zu setzen, zum Beispiel:

application_name = weekly-revenue-report

Dies würde für jede Client-Anwendung festgelegt werden, die sich mit Ihrem PostgreSQL-Server verbindet.