Um zu kontrollieren, ob die Replikation auch weiterhin funktioniert, kann man einerseits die Prozesstitel der laufenden PostgreSQL-Prozesse kontrollieren (Listing 4). Die hochzählende hexadezimale Zahl gibt die Position des Senders beziehungsweise Empfängers im aktuellen WAL-Segment an. Zusätzlich gibt es einige Funktionen, die man am Master und Slave ausführen kann, um zu sehen, ob die Replikation voranschreitet (Listing 5).
Listing 4: Replikationsprozesse monitoren
01 pgmaster:~# ps ‑ef | grep postgres 02 postgres 2575 2530 0 18:56 ? 00:00:01 postgres: wal sender process replication 10.211.55.9(54313) streaming 0/41B60F0 03 [..]
04 pgmaster:~# 05 pgslave:~# ps ‑ef | grep postgres 06 [..]
07 postgres 3443 3436 0 18:56 ? 00:00:00 postgres: startup process recovering 000000010000000000000004 08 postgres 3446 3436 0 18:56 ? 00:00:00 postgres: wal receiver process streaming 0/4194468 09 pgslave:~#
Listing 5: Erfolgskontrolle
01 pgmaster:~# psql postgres ‑c "SELECT pg_current_xlog_location();" 02 pg_current_xlog_location 03 ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑ 04 0/4279198 05 06 pgmaster:~# 07 pgslave:~# psql postgres ‑c "SELECT pg_last_xlog_receive_location(), pg_last_xlog_replay_location();" 08 pg_last_xlog_receive_location | pg_last_xlog_replay_location 09 ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑+‑‑‑‑‑ 10 11 0/42D67A8 | 0/42D67A8 12
Da PostgreSQL nur WAL-Einträge generiert, wenn es Transaktionen durchführt, ändern sich die gezeigten Zähler nur, wenn sich in der Datenbank Einträge ändern. Um zu erkennen, ob es zu Problemen beim Datenaustausch zwischen Master und Slave gekommen ist, kann man die »current_xlog_location« am Master mit der »last_xlog_receive_location« vergleichen. Um festzustellen ob es am Slave Probleme beim Einspielen der Änderungen gibt kann man hier die »last_xlog_receive_location« mit der »last_xlog_replay_location« vergleichen.
Die »receive_location« gibt die Position des letzten empfangenen WAL-Segments an. Die »replay_location« hingegen kennzeichnet die Position im WAL, bis zu der alle Transaktionen bereits auf die lokalen Heap-Files übernommen wurden und somit für Abfragen von Clients sichtbar sind.
Falls Receive und Replay Location auseinander driften, kann das mehrere Gründe haben. Ein naheliegender Grund wäre, dass der Slave I/O-mäßig überfordert ist. Sehr hilfreich beim Beobachten vieler Vitalparameter von PostgreSQL ist auch »check_postgres« [5] .
Ein weiteres Problem, das beim Betrieb von Hot Stand-by Server berücksichtigt werden muss, ist das der Query Conflicts. Es ist nämlich möglich, dass der Master Änderungen im WAL vermerkt, die auf dem Slave-Server Daten überschreiben oder entfernen würden, wobei eine laufende Abfrage genau diese Daten noch benötigt. Insbesondere Cleanups des Master führen zu solchem Kollisionen. Ein Clean up entfernt nicht mehr benötigte Tuple-Versionen, die für keine der Transaktionen am Master mehr sichtbar sind. Da der Master nicht über die Transaktionen auf den Slaves bescheid weiß, kann es dabei passieren, dass er Tuple entfernt, die ein Slave zum Beantworten einer laufenden Abfrage noch benötigt.
Eine andere Quelle für Query Conflicts können vom Master gesetzte Locks sein. Diese werden einerseits durch laufende Änderungen am Datenbankschema verursacht, können aber auch durch explizite Lock-Statements erzeugt werden. Weil ein Slave das WAL nur sequenziell abarbeiten kann und keine Bereiche überspringen darf, muss die Datenübernahme nun solange warten, bis die blockierenden Abfragen am Slave beendet sind. Da bei einem Query Conflict ein nicht kooperativer Client mit sehr lang laufenden Abfragen die Daten des Slave fast unbegrenzt altern lassen könnte, hat PostgreSQL 9 eingebaute Vorbeugemaßnahmen.
Der Parameter »max_standby_streaming_delay« ist standardmäßig auf 30 Sekunden gesetzt und gibt an, wie lang PostgreSQL das Einspielen neuer Daten anhalten darf, bevor es die blockierende Abfrage oder Verbindung am Slave terminiert. Maßgeblich hierfür ist der Empfangszeitpunkt des WAL-Eintrages. Sollte dieser Mechanismus auslösen, wird dies im Logfile am Slave vermerkt:
FATAL: terminating connection due to conflict with recovery DETAIL: User query might have needed to see row versions that must be removed. HINT: In a moment you should be able to reconnect to the database and repeat your command.
Um die Frequenz von Query Conflicts durch Cleanups zu reduzieren, gibt es den Parameter »vacuum_defer_cleanup_age«, mit dem man eine Schonfrist für nicht mehr benötigte Tuple definieren kann. Standardmäßig entfernt Postgres diese Tuple, sobald sie der Vacuum-Prozess entdeckt. Mit »vacuum_defer_cleanup_age« kann man einen zusätzlichen Puffer einführen, um bei Tables mit hohem Update- beziehungsweise Delete-Aufkommen die Konfliktwahrscheinlichkeit zu reduzieren.