View a markdown version of this page

Vermeiden von Leistungsproblemen mit REPLICA IDENTITY FULL in - Amazon Relational Database Service

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Vermeiden von Leistungsproblemen mit REPLICA IDENTITY FULL in

Für die logische PostgreSQL-Replikation muss jede veröffentlichte Tabelle über eine Replikatidentität verfügen, damit der Abonnent die richtige Zeile zum Aktualisieren oder Löschen finden kann. Standardmäßig dient der Primärschlüssel als Replikatidentität. Wenn eine Tabelle keinen Primärschlüssel oder keinen geeigneten eindeutigen Index hat, können Sie die Replikatidentität auf setzenFULL, was dazu führt, dass PostgreSQL die gesamte Zeile als Schlüssel verwendet.

Dies REPLICA IDENTITY FULL behebt zwar das unmittelbare Problem der Replikation von Tabellen ohne Primärschlüssel, kann jedoch zu schwerwiegenden Leistungseinbußen sowohl für den Herausgeber als auch für den Abonnenten führen. Das Verständnis dieser Auswirkungen ist für jeden wichtig, der logische Replikation mit verwendet, einschließlich Funktionen, die intern auf logischer Replikation basieren, wie z. B. Bereitstellungen. blue/green

Warum REPLICA IDENTITY FULL Probleme verursacht

Das WAL-Volumen auf dem Publisher wurde erhöht

Die REPLICA IDENTITY Einstellung steuert, welche Informationen PostgreSQL in das Write-Ahead-Log (WAL) schreibt, um Zeilen zu identifizieren, die aktualisiert oder gelöscht werden. Bei der standardmäßigen Replikatidentität (Primärschlüssel) werden nur die Schlüsselspalten als alte Zeilenidentität protokolliert. Mit FULL zeichnet PostgreSQL die alten Werte jeder Spalte für jedes UPDATE und auf. DELETE Das hat mehrere Konsequenzen:

  • Die WAL-Größe nimmt erheblich zu. Bei Aktualisierungen verdoppelt sich die Größe jedes WAL-Datensatzes ungefähr, da sowohl alte als auch neue Werte für jede Spalte aufgezeichnet werden. Wenn die Tabelle große Werte enthält, die mit TOAST gespeichert wurden, kann der Anstieg viel größer sein, da TOASTED-Werte abgerufen und in die WAL geschrieben werden müssen, auch wenn sie durch das Update nicht geändert wurden.

  • Höhere I/O CPU-Auslastung auf dem Publisher. Die zusätzlichen WAL-Schreibvorgänge verbrauchen mehr I/O Festplattenbandbreite und CPU-Zyklen, insbesondere bei schreibintensiven Workloads.

  • Es werden mehr Daten an Abonnenten gesendet. Der Herausgeber muss größere WAL-Datensätze über das Netzwerk an jeden Abonnenten übertragen, was den Bandbreitenverbrauch erhöht.

Langsame Zeilenabfragen auf dem Abonnenten

Wenn der Abonnent einen UPDATE DELETE Oder-Protokolldatensatz erhält, muss er die entsprechende Zeile in seiner lokalen Kopie der Tabelle finden. Mit REPLICA IDENTITY FULL sucht der Abonnent nach einer Zeile, die allen Spaltenwerten aus dem alten Zeilenbild entspricht.

Wie PostgreSQL diese Suche durchführt, unterscheidet sich je nach PostgreSQL-Hauptversion:

  • Vor PostgreSQL 16: Wenn die Tabelle keinen Primärschlüssel und keinen explizit konfigurierten Replikat-Identitätsindex hat, führt der Abonnent für jede einzelne OR-Operation einen sequentiellen Scan der gesamten Tabelle durch. UPDATE DELETE Bei großen Tabellen verlangsamt dies die Anwendungsleistung extrem.

  • PostgreSQL 16 und höher: Der Abonnent kann einen Btree- oder Hash-Index für Zeilensuchen verwenden, auch wenn dieser Index nicht explizit als Replikatidentität festgelegt ist. Der Abonnent bewertet jedoch nicht, welcher Index am effizientesten ist. Ab Version 16 wählt PostgreSQL den ersten geeigneten Index aus, den es findet, und der Benutzer hat keine Kontrolle über diese Auswahl. Wenn der ausgewählte Index eine geringe Selektivität aufweist (z. B. ein Index für eine boolesche Spalte oder eine Statusspalte), kann die Zeilensuche fast so langsam sein wie ein sequentieller Scan. Aus diesem Grund REPLICA IDENTITY FULL ist es unzuverlässig, sich auf die implizite Indexauswahl mit zu verlassen. Sie sollte daher als Fallback und nicht als empfohlene Konfiguration betrachtet werden.

Wie REPLICA IDENTITY FULL zu Verzögerungen bei der Replikation führt

Die beiden oben beschriebenen Probleme — größere WAL auf dem Herausgeber und langsamere Zeilenabfragen auf dem Abonnenten — führen zusammen zu Verzögerungen bei der Replikation.

Standardmäßig verwendet die logische PostgreSQL-Replikation einen einzigen Apply-Worker-Prozess pro Abonnement, um Änderungen vom Herausgeber zu empfangen und sie auf die Tabellen des Abonnenten anzuwenden. Der Apply-Worker verarbeitet Änderungen nacheinander, eine Zeile nach der anderen, in der Commit-Reihenfolge. Das bedeutet, dass der Durchsatz des Abonnenten dadurch begrenzt ist, wie schnell er jede einzelne Änderung anwenden kann.

Wenn für eine Tabelle ohne entsprechenden Index festgelegt REPLICA IDENTITY FULL wird, DELETE erfordert jedes UPDATE und einen sequentiellen Scan der gesamten Tabelle, um die passende Zeile zu finden. Wenn die Tabelle Millionen von Zeilen enthält, kann jeder dieser Vorgänge Sekunden oder länger dauern. Das Ergebnis ist ein kaskadierendes Problem:

  1. Der Herausgeber generiert Änderungen schneller, als der Abonnent sie anwenden kann. Die Schreibarbeitslast des Herausgebers läuft mit normaler Geschwindigkeit weiter, aber der Apply-Worker des Abonnenten hat bei sequentiellen Scans oder schlecht selektiven Indizes für jede Zeilensuche Engpässe.

  2. WAL sammelt sich auf dem Herausgeber an und kann den Speicherplatz erschöpfen. PostgreSQL kann WAL-Segmente erst zurückfordern, wenn der Abonnent bestätigt hat, dass er sie angewendet hat. Wenn der Abonnent weiter zurückfällt, sammelt der Herausgeber WAL auf der Festplatte an. Auf RDS for PostgreSQL scheint dies zuzunehmen. OldestReplicationSlotLag CloudWatch In schweren Fällen kann dies den gesamten verfügbaren Speicherplatz beanspruchen und dazu führen, dass der Herausgeber keine Schreibvorgänge mehr akzeptiert.

  3. Die Verzögerung verstärkt sich von selbst. Wenn der Abonnent ins Hintertreffen gerät, wächst die Tabelle über den Abonnenten aufgrund replizierter Einfügungen weiter an, wodurch jeder sequentielle Scan noch langsamer wird. Ohne Eingreifen nimmt die Verzögerung unbegrenzt zu.

Dieses Problem ist besonders gravierend bei Tabellen, die häufig UPDATE bearbeitet DELETE werden. INSERTOperationen sind nicht betroffen, da für sie keine Zeilensuche auf dem Abonnenten erforderlich ist.

Anmerkung

Ab PostgreSQL 16 kann der Apply-Worker Parallel-Apply für große Streaming-Transaktionen verwenden, was den Durchsatz verbessern kann. Der grundlegende Engpass bei der Zeilensuche REPLICA IDENTITY FULL ohne Indizes bleibt jedoch bestehen, da jede einzelne Zeile immer noch gescannt werden muss, um sie zu finden.

blue/green Auswirkungen auf Bereitstellungen

Blue/green Bereitstellungen in Amazon RDS verwenden intern logische Replikation, um die grüne Umgebung mit der blauen Umgebung zu synchronisieren, indem ein einziges Abonnement pro Datenbank eingerichtet wird. Der Prozess zum Anwenden der logischen Replikation in der grünen Umgebung erfolgt über einen einzigen Thread. Ein einziger Apply-Worker-Prozess empfängt alle Änderungen aus der blauen Umgebung und wendet sie nacheinander in der Commit-Reihenfolge an. Im blue/green Replikationspfad gibt es keine parallel Anwendung.

Dieses Single-Thread-Design bedeutet, dass die Fähigkeit der grünen Umgebung, mit der blauen Umgebung Schritt zu halten, ausschließlich davon abhängt, wie schnell ein Anwendungsmitarbeiter jede einzelne Änderung bearbeiten kann. Wenn Tabellen REPLICA IDENTITY FULL ohne Primärschlüssel oder geeigneten Index verwendet werden, hängen die Auswirkungen auf den Apply-Worker von der PostgreSQL-Version ab. In Versionen vor 16 zwingt jede Eingabe UPDATE dieser Tabellen den Apply-Worker, einen sequentiellen Scan der gesamten Tabelle durchzuführen, um die passende Zeile zu finden. DELETE In den Versionen 16 und höher verwendet PostgreSQL einen geeigneten Index, sofern einer verfügbar ist. Wenn jedoch kein qualifizierender Index vorhanden ist, greift der Apply-Worker trotzdem auf einen sequentiellen Scan zurück. Während der Apply-Worker eine große Tabelle nach einer Zeile durchsucht, werden alle anderen ausstehenden Änderungen in allen Tabellen in eine Warteschlange gestellt und warten.

Die Folgen für blue/green Bereitstellungen sind erheblich:

  • Die Verzögerung bei der Replikation nimmt kontinuierlich zu. Wenn die blaue Umgebung Schreibdatenverkehr schneller generiert, als der einzelne Apply-Worker ihn verarbeiten kann, fällt die grüne Umgebung immer weiter zurück. Da der Apply-Worker Single-Thread-fähig ist, gibt es keine Möglichkeit, den Catch-up zu parallelisieren.

  • Switchover kann blockiert werden. Ein blue/green Switchover erfordert, dass die grüne Umgebung vollständig mit der blauen Umgebung synchronisiert ist. Wenn die Replikationsverzögerung zu hoch ist, kann der Switchover nicht innerhalb des Timeout-Zeitraums abgeschlossen werden.

  • Die grüne Umwelt wird vielleicht nie aufholen. Bei schreibintensiven Workloads, bei denen große Tabellen verwendet werden REPLICA IDENTITY FULL und keine Indizes verwendet werden, kann die Anwendungsrate so langsam sein, dass die grüne Umgebung dauerhaft ins Hintertreffen gerät, sodass ein Switchover ohne vorherige Auflösung der Konfiguration der Replikatidentität unmöglich wird.

  • WAL sammelt sich in der blauen Umgebung an. Während sich die grüne Umgebung dahinter befindet, behält die blaue Umgebung WAL-Segmente für den Replikationsslot bei. Dies erhöht die Speicherauslastung in der blauen (Produktions-) Umgebung und kann die Produktionsleistung beeinträchtigen.

Um diese Probleme zu vermeiden, stellen Sie sicher, dass alle Tabellen über einen Primärschlüssel oder einen geeigneten eindeutigen Index verfügen, der explizit als Replikatidentität konfiguriert ist, ALTER TABLE ... REPLICA IDENTITY USING INDEX bevor Sie eine blue/green Bereitstellung erstellen. Verlassen Sie sich nicht auf REPLICA IDENTITY FULL die implizite Indexauswahl in PostgreSQL 16+, da der Abonnent möglicherweise einen schlecht selektiven Index wählt oder auf sequentielle Scans zurückgreift. Testen Sie die Bereitstellung mit einem repräsentativen Schreib-Workload, um sicherzustellen, dass die grüne Umgebung Schritt halten kann.

Weitere Informationen zu Einschränkungen bei der blue/green Bereitstellung finden Sie unterEinschränkungen und Überlegungen für Amazon RDS Amazon . Bewährte Methoden finden Sie unter Bewährte Methoden für Bereitstellungen in RDS für PostgreSQL blue/green.

Wie identifiziert man Tabellen mit REPLICA IDENTITY FULL

Führen Sie die folgende Abfrage aus, um alle Tabellen mit REPLICA IDENTITY FULL zu finden:

SELECT n.nspname AS schema, c.relname AS table_name, c.relreplident FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' AND c.relreplident = 'f' AND n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY n.nspname, c.relname;

Die relreplident Spaltenwerte sind:

  • d— Standard (Primärschlüssel)

  • n— nichts

  • f— voll (ganze Zeile)

  • i— ein bestimmter Index

Behelfslösungen und bewährte Verfahren

Fügen Sie, wo immer möglich, einen Primärschlüssel hinzu

Die effektivste Lösung besteht darin, Tabellen, denen einer fehlt, einen Primärschlüssel hinzuzufügen. Wenn ein Primärschlüssel vorhanden ist, verwendet PostgreSQL ihn als Standardreplikatidentität, wodurch effiziente Zeilenabfragen auf dem Abonnenten ermöglicht und der WAL-Overhead für den Herausgeber minimiert wird.

ALTER TABLE my_table ADD COLUMN id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY;
Wichtig

Diese Anweisung erwirbt eine ACCESS EXCLUSIVE Sperre und schreibt die gesamte Tabelle neu, da der Standardwertausdruck den Volatile-Wert verwendet. nextval() Alle Lese- und Schreibvorgänge in der Tabelle werden für die Dauer des Umschreibens blockiert. Bei großen Tabellen kann dies zu erheblichen Ausfallzeiten führen. Planen Sie diese Änderung während eines Wartungsfensters oder ziehen Sie alternative Vorgehensweisen in Betracht, z. B. indem Sie die Spalte zunächst als NULL-Wert definieren und dann die Einschränkung in separaten Schritten wieder auffüllen und hinzufügen.

Wenn das Hinzufügen eines Primärschlüssels aufgrund von Anwendungseinschränkungen nicht möglich ist, sollten Sie erwägen, einen eindeutigen Index für eine Gruppe von NOT NULL Spalten hinzuzufügen und ihn als Replikatidentität festzulegen:

CREATE UNIQUE INDEX my_table_replica_idx ON my_table (col1, col2); ALTER TABLE my_table REPLICA IDENTITY USING INDEX my_table_replica_idx;
Anmerkung

Um zu vermeiden, dass Schreibvorgänge während der Indexerstellung blockiert werden, verwenden Sie die folgende CONCURRENTLYKlausel: CREATE UNIQUE INDEX CONCURRENTLY my_table_replica_idx ON my_table (col1, col2);

Anmerkung

Der für die Replikatidentität verwendete Index muss eindeutig sein, darf nicht unvollständig sein, darf nicht aufschiebbar sein und darf nur Spalten mit Einschränkungen enthalten. NOT NULL

Verlassen Sie sich nicht auf die implizite Indexauswahl (PostgreSQL 16+)

Ab PostgreSQL 16 kann der Apply-Worker des Abonnenten Btree- oder Hash-Indizes für Zeilensuchen verwenden, wenn die Replikatidentität auf gesetzt istFULL, auch wenn diese Indizes nicht explizit als Replikatidentität konfiguriert sind. Dies verhindert zwar in einigen Fällen sequentielle Scans, aber sich auf dieses implizite Verhalten zu verlassen, ist aus den folgenden Gründen ein Anti-Pattern:

  • Sie haben keine Kontrolle darüber, welcher Index ausgewählt wird. PostgreSQL wählt den ersten qualifizierten Index, den es in der Katalogreihenfolge findet, aus, nicht den selektivsten oder effizientesten. Wenn die Tabelle mehrere qualifizierende Indizes hat, weist der gewählte Index möglicherweise eine geringe Selektivität auf, was zu einer schlechten Suchleistung führt.

  • Das Verhalten ist fragil. Durch das Hinzufügen, Löschen oder Neuerstellen von Indizes kann sich der vom Apply-Worker verwendete Index ändern, was möglicherweise zu unerwarteten Leistungseinbußen bei der Replikation führen kann.

  • Dadurch wird das zugrundeliegende Problem verschleiert. Tabellen ohne Primärschlüssel oder explizite Replikatidentität sind von Natur aus riskant für die logische Replikation. Sich auf die implizite Indexauswahl zu verlassen, verzögert das Problem, anstatt es zu lösen.

Konfigurieren Sie stattdessen explizit die Replikatidentität für jede replizierte Tabelle:

  • Beste Option: Fügen Sie einen Primärschlüssel hinzu. Dies ist die zuverlässigste und effizienteste Replikatidentität.

  • Alternative: Wird verwendetALTER TABLE ... REPLICA IDENTITY USING INDEX, um einen bestimmten eindeutigen, nicht partiellen, nicht aufschiebbaren Index zu kennzeichnen, der nur Spalten enthält. NOT NULL Dadurch haben Sie die explizite Kontrolle darüber, welche Spalten für die Zeilenidentifikation verwendet werden.

Reservieren Sie sich REPLICA IDENTITY FULL nur für Tabellen, bei denen keine der beiden Optionen möglich ist, und seien Sie sich darüber im Klaren, dass die Leistung von Faktoren abhängt, auf die Sie keinen direkten Einfluss haben.

Überwachen Sie die Verzögerung bei der

Überwachen Sie bei der Verwendung die Replikationsverzögerung genauREPLICA IDENTITY FULL, um zu erkennen, dass die Anwendungen der Abonnenten langsamer werden, bevor sie kritisch werden.

Überprüfen Sie auf dem Herausgeber die Verzögerung zwischen der aktuellen WAL-Position und dem, was der Abonnent bestätigt hat:

SELECT slot_name, confirmed_flush_lsn, pg_current_wal_lsn(), (pg_current_wal_lsn() - confirmed_flush_lsn) AS lag_bytes FROM pg_replication_slots WHERE slot_type = 'logical';

Ein stetig steigender lag_bytes Wert deutet darauf hin, dass der Abonnent ins Hintertreffen gerät. Die pg_stat_replication_slots Ansicht bietet zusätzliche Statistiken zur Nutzung der einzelnen Replikationssteckplätze.

Auf dem Abonnenten wird in der pg_stat_subscription Ansicht der Status jedes einzelnen Apply-Workers angezeigt, einschließlich des zuletzt empfangenen und gemeldeten WAL-Standorts:

SELECT subname, received_lsn, latest_end_lsn, last_msg_send_time, last_msg_receipt_time FROM pg_stat_subscription;
Anmerkung

In PostgreSQL 16 und höher können Sie auch wählen, ob Sie zwischen dem worker_type Haupt-Apply-Worker und dem parallel Apply-Worker unterscheiden möchten.

Eine große Lücke zwischen received_lsn und latest_end_lsn oder veraltete Zeitstempel können darauf hindeutenlast_msg_send_time, dass der Apply-Worker Schwierigkeiten hat, Schritt zu halten. In der pg_stat_subscription_stats Ansicht werden auch Anwendungsfehler und Konflikte erfasst, die zu Verzögerungen führen könnten.

Für RDS for PostgreSQL können Sie auch die OldestReplicationSlotLag CloudWatch Metrik überwachen, die die Verzögerung in Byte des Replikationssteckplatzes mit der größten Verzögerung verfolgt. Ein steigender Wert ist ein Frühwarnsignal für eine Verzögerung bei der Replikation.

Überprüfen, welche Tabellen während der Anwendung möglicherweise einen suboptimalen Index verwenden

Auf dem Abonnenten können Sie Tabellen identifizieren, in denen der Apply-Worker zu viele Heap-Lesevorgänge durchführt, was darauf hindeuten kann, dass die Tabelle beim Anwenden keinen effizienten Index für die Zeilensuche hat. Führen Sie die folgende Abfrage auf dem Abonnenten aus:

SELECT relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, heap_blks_read + heap_blks_hit AS total_heap_access FROM pg_statio_user_tables WHERE heap_blks_read > 0 ORDER BY heap_blks_read DESC LIMIT 10;

Eine Tabelle mit einem hohen heap_blks_read Wert im Verhältnis zu idx_blks_read kann darauf hinweisen, dass der Apply-Worker keinen effizienten Index verwendet, um Zeilen für UPDATE und DELETE Operationen zu finden. Dies ist eine häufige Ursache für Replikationsverzögerungen, wenn er verwendet REPLICA IDENTITY FULL wird.

Anmerkung

Für diese Abfrage muss der track_countsParameter auf dem Abonnenten aktiviert sein. Dieser Parameter ist standardmäßig aktiviert.

Prüfen Sie, ob REPLICA IDENTITY FULL erforderlich ist

Überlegen Sie sich vor der EinstellungREPLICA IDENTITY FULL, ob Sie es wirklich benötigen. Zu den häufigsten Gründen für die Verwendung gehören:

  • Die Tabelle hat keinen Primärschlüssel oder eindeutigen Index.

  • Sie benötigen das vollständige Before-Image der Zeilen für CDC-Benutzer (Change Data Capture).

  • Sie benötigen in Replikationsereignissen enthaltene Toasted-Spaltenwerte für Aktualisierungen, die diese Spalten nicht ändern.

Wenn Ihr einziger Grund das Fehlen eines Primärschlüssels ist, ist das Hinzufügen eines Primärschlüssels fast immer der bessere Weg. Wenn Sie vollständige Before-Images für CDC benötigen, sollten Sie überlegen, ob Ihr CDC-Benutzer ganze Zeilen rekonstruieren kann, indem er den Status extern beibehält, wodurch der WAL- und Abonnentenaufwand von vermieden wird. REPLICA IDENTITY FULL

Zusammenfassung der Empfehlungen

Szenario Empfehlung
Die Tabelle hat einen Primärschlüssel Verwenden Sie die Standardreplikatidentität (keine Aktion erforderlich)
Die Tabelle hat einen eindeutigen NOT-NULL-Index Legen Sie diesen Index als Replikatidentität fest mit ALTER TABLE ... REPLICA IDENTITY USING INDEX
Die Tabelle hat keinen passenden Schlüssel (PostgreSQL 16+) Fügen Sie einen Primärschlüssel oder einen eindeutigen Index hinzu. Die Verwendung REPLICA IDENTITY FULL einer impliziten Indexauswahl ist unzuverlässig und sollte das letzte Mittel sein
Die Tabelle hat keinen geeigneten Schlüssel (vor PostgreSQL 16) Fügen Sie einen Primärschlüssel oder einen eindeutigen Index hinzu; vermeiden Sie diesREPLICA IDENTITY FULL, wenn möglich
Write-heavy Arbeitslast mit large/TOASTed Spalten Vermeiden Sie dies REPLICA IDENTITY FULL aufgrund der WAL-Lautstärkenverstärkung