Im Gegensatz zur physischen Replikation ist der Schreibzugriff auf den Teilnehmerknoten bei der logischen Replikation nicht deaktiviert. Dies bedeutet, dass DML–
und DDL-
Anweisungen wie INSERT
, UPDATE
, DELETE
oder ALTER
auf dem Abonnenten ausgeführt werden können. Da die Replikation jedoch unidirektional ist, werden diese Änderungen nicht zurück an den Herausgeber repliziert. Dieses Verhalten kann zu Problemen führen – die Replikation kann mit all ihren Konsequenzen gestoppt werden oder die Daten können nicht mehr synchron sein. In diesem Beitrag möchten wir einige Tipps zum Umgang mit solchen Problemen geben.
Zur Erinnerung können Sie hier noch einmal sehen, wie die Architektur der logischen Replikation umgesetzt ist.
Daten können problemlos in eine Replikationszieltabelle eingefügt werden, vorausgesetzt, eine Zeile mit identischer REPLICA-IDENTITÄT
wird anschließend nicht auf dem Herausgeberknoten eingefügt. Betrachten Sie beispielsweise die folgende Tabelle:
CREATE TABLE t1(id integer primary key, value integer, description varchar);
Die REPLICA-IDENTITÄT
verwendet den Standardschlüssel id
, der die Standardeinstellung ist.
Sie können das folgende INSERT
auf dem Abonnenten sicher ausführen:
INSERT INTO t1 VALUES (100, 1024, 'test');
Aber wenn Sie ein INSERT
mit identischem Primärschlüsselwert auf dem Herausgeber ausführen, z.B.:
INSERT INTO t1 VALUES (100, 65536, 'test on publisher');
wird Ihnen auf dem Abonnentenknoten eine Fehlermeldung, wie folgt, angezeigt:
ERROR: duplicate key value violates unique constraint "t1_pkey"
DETAIL: Key (id) = (100) already exists.
Die Replikation wird gestoppt und WAL-Segmente werden auf dem Herausgeber gesammelt. Glücklicherweise enthält das Protokoll alle erforderlichen Informationen und Sie müssen die problematische Zeile mit folgendem Befehl auf dem Abonnenten löschen:
DELETE FROM t1 WHERE id=100;
Anschließend wird die Replikation automatisch neu gestartet.
Solange die erforderlichen Berechtigungen gewährt werden, können UPDATE
-Anweisungen ohne Fehler oder Warnungen auf dem Abonnenten ausgeführt werden. Die Replikation wird nicht angehalten. Der Herausgeber weiß jedoch nichts über die Änderung. Infolgedessen können sich die Werte in derselben Zeile zwischen Herausgeber und Abonnent unterscheiden. Wenn jedoch dieselbe Zeile beim Herausgeber aktualisiert wird, wird die gesamte Zeile beim Abonnenten überschrieben und die Änderung wird gelöscht, selbst wenn die Änderungen an verschiedenen Spalten vorgenommen wurden.
Diese Art von Inkonsistenz führt nicht dazu, dass die Replikation gestoppt wird. Wenn Ihr Konfigurationsparameter log_min_messages
auf einen niedrigeren Wert als debug1
eingestellt ist, werden Sie ihn wahrscheinlich nicht bemerken. Wenn Sie Debug-Meldungen protokollieren und eine Zeile im Herausgeber aktualisieren/löschen, die auf dem Abonnenten nicht vorhanden ist, sollten Sie folgende Protokolleinträge auf dem Abonnentenknoten erwarten:
DEBUG: logical replication did not find row for update in replication target relation "t1"
DEBUG: logical replication did not find row for delete in replication target relation "t1"
Manchmal ist es erwünscht, einen kleineren Datensatz auf dem Abonnenten zu halten und solche Nachrichten können sicher ignoriert werden. Aber was ist, wenn es eine Inkonsistenz ist, die gelöst werden muss? Leider bietet die native logische Replikation im Gegensatz zu pglogical
keine Tools zum erneuten Synchronisieren der Tabelle.
Dafür gibt es allerdings einen weiteren Weg dieses Problem zu umgehen.
Sie haben hier verschiedene Möglichkeiten:
Wenn es Ihnen nichts ausmacht, die Systemkataloge von Hand zu bearbeiten, gibt es noch eine weitere Möglichkeiten:
Beachten Sie, dass Sie unbedingt über ein Backup verfügen sollten, wenn sie fortfahren.
Der Status logisch replizierter Tabellen wird in einer Tabelle pg_subscription_rel
gespeichert. Die Spalte srsubstate
gibt an, ob die Tabelle initialisiert wird, Daten kopiert und synchronisiert werden oder ob die Replikation bereit ist. Wenn Sie den Wert in i
ändern, was initial
bedeutet, können Sie das Starten der anfänglichen Synchronisation erzwingen. Führen Sie den folgenden Befehl für den Abonnenten aus, um eine Tabelle mit dem Namen t1
erneut zu synchronisieren:
TRUNCATE TABLE t1;
UPDATE pg_subscription_rel SET srsubstate = 'i' WHERE srrelid = (SELECT relid FROM pg_stat_user_tables WHERE schemaname='public' AND relname='t1');
(Wenn sich die Tabelle in einem anderen Schema befindet, ersetzen Sie public
durch den entsprechenden Schemanamen.)
Überprüfen Sie nach einer Weile die Tabelle pg_subscription_rel
. Der Status sollte sich automatisch zunächst in d
, dann s
und schließlich in r
ändern, was bedeutet, dass die Neusynchronisation abgeschlossen ist. Wenn der Status bei d hängt, überprüfen Sie die Protokolle und pg_stat_replication
am Herausgeberknoten. Wenn die Replikation aufgrund eines doppelten Primärschlüsselwerts fehlschlägt, löschen Sie die Daten auf dem Abonnenten, überprüfen Sie ob die Zeilenanzahl tatsächlich Null ist und wiederholen Sie die Aktualisierung von pg_subscription_rel.
Kontaktieren Sie uns gerne über das
Kontaktformular und vereinbaren ein unverbindliches
Beratungsgespräch mit unseren Berater:innen zur
Bedarfsevaluierung. Gemeinsam optimieren wir Ihre
Umgebung und steigern Ihre Performance!
Wir freuen uns auf Ihre Kontaktaufnahme!