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

PostgreSQL:Sechs nicht so einfache Stücke

PostgreSQL verfügt über eine Reihe hervorragender Funktionen, die im Open-Source-RDBMS-Bereich ihresgleichen suchen. Es ist größtenteils einfach zu erlernen und zu verwenden, insbesondere für Anwendungsentwickler. Einige Teile sind jedoch, nun ja, einfach nicht einfach. Sie erfordern Arbeit, um sie einzurichten und richtig zu machen, und sind in der Regel auch unternehmenskritisch.

Verbindungsverwaltung

PostgreSQL startet einen neuen Prozess, der als Backend-Prozess bezeichnet wird , um jede Verbindung zu handhaben. Dies steht im Gegensatz zu modernen Verbindungsverarbeitungsarchitekturen auf Eventloop-/Threadpool-Basis, die in vergleichbarer Serversoftware zu finden sind. Das Erzeugen eines vollständigen Prozesses nimmt mehr Zeit und Ressourcen in Anspruch und äußert sich in erhöhten Abfragelatenzen in Anwendungen, in denen Verbindungen mit hoher Geschwindigkeit geöffnet und geschlossen werden.

In den meisten Bereitstellungen ist auf einer bestimmten Ebene ein Pooling von Verbindungen erforderlich. Auf Anwendungsebene kann dies die Verwendung Ihrer Programmiersprache/Bibliotheksfunktionen sein. Zum Beispiel kann sql/DB.SetMaxIdleConn verwendet werden, um die Wiederverwendung von Verbindungen innerhalb einer einzelnen Go-Anwendung zu erhöhen.

Oft müssen Sie jedoch eine Verbindungspooling- oder Lastausgleichslösung eines Drittanbieters verwenden. Verbindungspooler verwalten einen Pool von Leerlaufverbindungen zum Upstream-Postgres-Server, die eingehenden Clientverbindungen zugewiesen und per Proxy weitergeleitet werden. Sie parsen normalerweise die von Clients gesendete SQL, um Transaktionsgrenzen und datenmodifizierende DMLs zu erkennen, um Funktionen wie Verbindungspooling auf Transaktionsebene und Read Replicas zu implementieren.

PgBouncer ist ein beliebter, leichtgewichtiger Single-Binary-Connection-Pooler und wird oft zusammen mit PostgreSQL im selben System ausgeführt.

PgPool ist vielseitiger als PgBouncer. Es kann beispielsweise auch Load Balancing und Replikation durchführen.

Verbindungspooling bringt jedoch seine eigenen Kopfschmerzen mit sich. Erstens ist es ein zusätzliches bewegliches Teil, das in Ihrer Bereitstellung gewartet werden muss. Das Einrichten der Authentifizierung ist auch mühsam, wenn Sie Clients haben, die unterschiedliche Anmeldeinformationen oder Authentifizierungsmechanismen verwenden. Einige Funktionen auf Verbindungsebene wie LISTEN/NOTIFY, vorbereitete Anweisungen, temporäre Tabellen und dergleichen erfordern möglicherweise eine zusätzliche Konfiguration oder clientseitige Änderungen, damit sie funktionieren.

Zero-Downtime-Upgrades

Das Upgrade von PostgreSQL zwischen Nebenversionen (13.x -> 13.y) umfasst die Installation des neuen Pakets und den Neustart des Serverprozesses. Während ein Neustart des Serverprozesses zwangsläufig alle verbundenen Clients unterbricht, ist dies dennoch eine vernünftige Bitte, da die Ausfallzeit an die Dauer eines Dienstneustarts gebunden ist.

Ein Upgrade zwischen Hauptversionen (12.x -> 13.y) ist jedoch eine viel größere Sache. Je mehr Daten vorhanden sind, desto schmerzhafter ist der Prozess normalerweise.

Die einfachste Methode, die nur für geringe Datenmengen (z. B. Dutzende von GB) funktioniert, besteht darin, die Daten der alten Version auszugeben und auf einem Server der neuen Version wiederherzustellen. Eine weitere Option ist die Verwendung von pg_upgrade, was einen orchestrierten Tanz erfordert mit Binärdateien beider Postgres-Versionen.

In beiden Fällen wären die Datenbanken für eine beträchtliche Zeit ausgefallen.

Idealerweise sollte es möglich sein, auf einen Server der neuen Version zu replizieren und den Server der neuen Version als primären Server hochzustufen. Es ist jedoch nicht möglich, eine Streaming-Replikation auf einen Standby-Server mit einer anderen Hauptversion durchzuführen. Die logische Replikation scheint zwar gut geeignet für die Aufgabe zu sein, hat jedoch gewisse Fallstricke, die umgangen werden müssen, um eine vollständige Replikation sicherzustellen.

Die meisten HA-Lösungen für Postgres basieren auf Streaming-Replikation, daher können Sie Knoten in einem Cluster nicht einzeln aktualisieren.

Der aktuelle Stand der Technik wäre die Verwendung der logischen Replikation, während die Einschränkungen der logischen Replikation umgangen werden und möglicherweise einschränkende Funktionen enthalten sind, die Anwendungen (wie DDLs) während der Upgrade-Phase verwenden können.

Hohe Verfügbarkeit

PostgreSQL verfügt über alle Low-Level-Funktionen, die zum Erstellen einer HA-Lösung erforderlich sind:Replikation mit Feedback, kaskadierende Replikation, synchrone Replikation, Standbys, Hot-Standbys, Standby-Promotion und so weiter. Es bietet jedoch keine HA-Lösung „out of the box“. Es gibt keine Frameworks oder Tools zum Überwachen des Zustands und zum automatischen Failover auf einen Standby-Server. Es gibt keine Vorstellung von einem Multi-Node-HA-Cluster.

Sie müssen eine Drittanbieterlösung einrichten und ausführen, um hochverfügbare Postgres-Bereitstellungen zu erstellen. Aktuelle Favoriten sind pg_auto_failover und Patroni. Während Patroni auf einen bestehenden hochverfügbaren Konfigurationsspeicher wie ZooKeeper oder etcd setzt, kommt pg_auto_failover auch ohne aus.

Eines davon in der Produktion zu evaluieren, bereitzustellen und zu testen, erfordert Zeit und Mühe. Monitoring, Alerting und Operations Playbooks müssen eingerichtet und gewartet werden.

Bloat-Management

Die MVCC-Architektur von PostgreSQL bedeutet, dass niemals Daten überschrieben werden – das Ändern einer Zeile führt nur dazu, dass eine neue Version der Zeile auf die Festplatte geschrieben wird. Das Löschen einer Zeile bedeutet nur, dass aufgezeichnet wird, dass die Zeile für zukünftige Transaktionen unsichtbar ist. Wenn auf eine Zeilenversion von laufenden oder zukünftigen Transaktionen aus nicht zugegriffen werden kann, ist sie nicht mehr von Nutzen und wird als „Bloat“ bezeichnet. Der Prozess des Garbage-Collection dieser Aufblähung wird „Vakuum“ genannt.

Bloat ist für Anwendungen unsichtbar und verursacht allein dem DBA Kopfschmerzen. Bei aktualisierungsintensiven Tabellen ist die Überwachung und Verwaltung von Bloat ein nicht triviales Problem. Der Autovacuum-Prozess hilft sehr, aber seine Schwellenwerte müssen möglicherweise global oder pro Tag tablelevel, um sicherzustellen, dass Tabellengrößen nicht unüberschaubar groß werden.

Auch Indizes sind von Blähungen betroffen, hier hilft kein Autovacuum. Das Löschen von Zeilen und das Aktualisieren von indizierten Spalten führt zu toten Einträgen in Indizes. Updatelastige Workloads mit Updates auf indizierte Spalten können zu ständig wachsenden und ineffizienten Indizes führen. Es gibt kein Vakuumäquivalent für Indizes. Die einzige Lösung besteht darin, den gesamten Index mit REINDEX neu zu erstellen oder VACUUM FULL für die Tabelle zu verwenden.

Abgesehen von einem einzelnen Wert pro Tabelle (pg_stat_all_tables.n_dead_tup) bietet Postgres nichts zur Schätzung des Aufblähens in einer Tabelle und überhaupt nichts für Indizes. Der praktischste Weg bleibt immer noch das Ausführen einer gruselig aussehenden Abfrage von check_postgres.

pgmetrics enthält die Abfrage von check_postgres und kann eine Ausgabe im JSON- und CSV-Format erzeugen, die Größen- und Aufblähungsinformationen für alle Tabellen und Indizes enthält; die in Überwachungs- oder Automatisierungstools eingespeist werden können.

pg_repack ist eine beliebte Alternative zu VACUUM FULL – es kann den gleichen Job machen, aber ohne Sperren. Wenn Sie gezwungen sind, VACUUM FULL regelmäßig durchzuführen, ist dies ein Muss.

zheap ist die seit Jahren in der Entwicklung befindliche neue Speicher-Engine für Postgres, die durch In-Place-Updates eine Reduzierung der Aufblähung verspricht.

Abfrageplanverwaltung

Core PostgreSQL bietet in diesem Bereich nur zwei rudimentäre Tools:

  • pg_stat_statements Erweiterung für die Abfrageanalyse – dies gibt die Gesamt- und Durchschnittswerte der Abfrageplanungs- und -ausführungszeiten, Festplatten- und Speichernutzung
  • auto_explain -Erweiterung, die Abfrageausführungspläne in das Postgres-Protokollziel drucken kann

Während die von pg_stat_statements bereitgestellten Statistiken gerade ausreichen, um durchzukommen, verwenden Sie auto_explain Pläne in Protokolldateien zu zwingen und sie dann zu extrahieren, ist nicht wirklich mehr als ein Hack, besonders im Vergleich zu kommerziellen Konkurrenten von Postgres, die Planhistorie, Baselining und Verwaltungsfunktionen anbieten.

Der aktuelle Stand der Technik bei Postgres besteht darin, die Protokolldatei für Abfragepläne zu schürfen und sie an anderer Stelle zu speichern. Aber das vielleicht größte Handicapproblem besteht darin, den Abfrageplan nicht mit den entsprechenden Analysen aus pg_stat_statements verknüpfen zu können. pgDash tut dies, indem es sowohl die SQL-Abfragetexte von pg_stat_statements als auch die auto_explain-Ausgabe analysiert, die von pg_stat_statements vorgenommene Verstümmelung anpasst und versucht, die beiden abzugleichen. Es erfordert einen vollständigen PostgreSQL-Dialekt-SQL-Parser.

Baselining, Festlegen von Richtlinien für die Planauswahl usw. sind derzeit im Kern von PostgreSQL einfach nicht möglich.

Es gibt ein paar Erweiterungen, die im Grunde verbesserte Versionen von pg_stat_statements sind, aber die zusätzlichen Schritte, die mit der Verwendung einer Erweiterung eines Drittanbieters verbunden sind, machen es für die meisten Menschen zu einer Herausforderung, insbesondere wenn sie einen verwalteten Postgres-Anbieter verwenden.

Tuning

PostgreSQL bietet eine Fülle von Tuning-Optionen, beginnend mit der Einstellung under-configured-by-defaultshared_buffers. Einige sind einfach zu verstehen und festzulegen, wie die Anzahl paralleler Worker für verschiedene Operationen (max_worker_processes, max_parallel_* usw.). Andere sind etwas obskur (wal_compression, random_page_cost usw.), aber im Allgemeinen nützlich. Am ärgerlichsten sind jedoch diejenigen, die quantifizierbare Informationen über die Arbeitsbelastung benötigen.

Wenn beispielsweise work_mem zu niedrig ist, könnten Abfragen temporäre Festplattendateien verwenden; wenn sie zu hoch ist und genügend gleichzeitige Abfragen vorhanden sind, werden Postgres-Backend-Prozesse möglicherweise durch OOM zerstört. Wie finden Sie also heraus, auf welche Nummer Sie es einstellen müssen?

In der Praxis, insbesondere bei OLTP-Workloads und Webanwendungs-Workloads, ist es unmöglich vorherzusagen, wie hoch der Spitzenspeicherbedarf für Abfragen sein würde. Legen Sie am besten einen vernünftigen Wert fest und überwachen Sie dann Abfragen, um festzustellen, ob eine davon von einem höheren Wert von work_mem profitiert hätte.

Und wie machst du das? Sie benötigen die Erweiterung auto_explain um die Abfrageausführungspläne jeder Abfrage zu protokollieren, diese aus den Protokolldateien von Postgres zu extrahieren, jeden Abfrageplan zu untersuchen, um festzustellen, ob er festplattenbasierte externe Zusammenführungen oder einen Bitmap-Heap-Scan mit verlustbehafteten Heap-Blöcken verwendet.

Nicht unmöglich, nur schwer.