Zum Inhalt

PostgreSQL Hochverfügbarkeit: Physische Streaming-Replikation & Failover

Erstellt: 2026-11-08  ·  Zuletzt aktualisiert: 2026-11-08  ·  Nejat Hakan

Management Summary: Hochverfügbarkeit (High Availability, HA) in geschäftskritischen Datenbankarchitekturen schützt vor Hardwaredefekten, Kernel-Panics und Rechenzentrumsausfällen. PostgreSQL realisiert dies über physische Streaming-Replikation: Änderungen, die im Write-Ahead Log (WAL) des Primary-Knotens erfasst werden, werden Byte für Byte über TCP-Sockets an einen oder mehrere Standby-Replikas gestreamt. Dieser Praxisleitfaden führt durch den Aufbau eines stabilen Primary-Standby-Clusters unter Debian Linux, eliminiert WAL-Recycling-Probleme mittels Replikations-Slots, demonstriert das Klonen via pg_basebackup -R, überwacht Latenzen mit pg_stat_replication und vollzieht geplante sowie ungeplante Failover-Promotions.

  • Primary-Standby-Architektur


    Die Replikations-Pipeline verstehen: Wie der walsender des Primary binäre WAL-Records an den walreceiver und Startup-Prozess des Standbys streamt.

  • Replikations-Slots & Absicherung


    Schutz vor Desynchronisation: WAL-Segmente auf dem Primary sperren und Replikationstraffik über dedizierte Rollen und pg_hba.conf isolieren.

  • Knoten-Bootstrapping


    Unterbrechungsfreies Klonen laufender Instanzen: Durchführung von pg_basebackup -R mit automatischer standby.signal-Erzeugung.

  • Lag-Telemetrie & Failover


    Sub-Millisekunden-Replikationsdrift über pg_stat_replication überwachen und Standbys im Notfall via pg_promote() zur Primary befördern.


1. Architektur der physischen Streaming-Replikation

Die physische Replikation in PostgreSQL arbeitet direkt auf Page- und Block-Ebene des Speichersystems. Sobald eine schreibende Transaktion auf dem Primary-Server committet wird, werden die entsprechenden Änderungsdaten im Write-Ahead Log (WAL) fixiert. Ein Hintergrundprozess (walsender) streamt diese Bytes anschließend kontinuierlich über das Netzwerk an den Standby:

%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
    PRI["Primary-Knoten (Debian 12)<br/>Schreib- und Lesezugriffe"]
    WAL["Primary WAL Engine<br/>Schreibt in 16MB WAL"]
    WS["walsender Prozess<br/>Streamt Bytes via TCP"]
    WR["walreceiver Prozess<br/>Puffert Stream in WAL"]
    STARTUP["Startup Replay Prozess<br/>Spielt Deltas in Heap ein"]
    STANDBY["Standby-Knoten (Debian 12)<br/>Read-Only Queries"]

    PRI --> WAL
    WAL --> WS
    WS -->|"TLS-Stream (:5432)"| WR
    WR --> STARTUP
    STARTUP --> STANDBY

Abwägung: Synchrone vs. Asynchrone Replikation

Modus synchronous_commit Datenverlust-Garantie (RPO) Schreiblatenz (TPS-Einfluss) Betriebliche Besonderheiten
Asynchron (Standard) off oder local Minimales Fenster (letzte Millisekunden ungesendeten WALs) Keine zusätzliche Netzwerkverzögerung Maximaler Schreibdurchsatz. Primary committet sofort nach lokalem Flush.
Remote Write remote_write Sicher gegen Betriebssystem-Abstürze des Standbys Geringe Verzögerung (Netzwerk-RTT zum RAM des Standbys) Primary wartet, bis Standby den WAL im OS-Pufferspeicher bestätigt.
Synchron on Keinerlei Datenverlust (RPO = 0) Spürbare Verzögerung (Netzwerk-RTT + Standby-fsync) Primary blockiert den Commit, bis der Standby den WAL auf Festplatte gesichert hat.
Remote Apply remote_apply Read-your-Writes-Konsistenz über alle Knoten Höchste Latenzeinbußen Primary wartet, bis Standby die Änderungen vollständig in den Heap eingespielt hat.

2. Primary-Konfiguration & Sicherheitsabsicherung

Auf dem Primary-Server (192.168.10.10) wird PostgreSQL so konfiguriert, dass ausreichend WAL-Segmente vorgehalten und Replikationsverbindungen zugelassen werden.

2.1. Anpassungen in postgresql.conf

# Datei: /etc/postgresql/16/main/postgresql.conf

# Replikationsmodus aktivieren
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10

# Ausreichend WAL-Puffer vorhalten bei Netzwerk-Unterbrechungen
wal_keep_size = 4096MB

# Leseabfragen im Standby-Modus erlauben
hot_standby = on

# Kontinuierliche WAL-Archivierung (empfohlenes Sicherheitsnetz)
archive_mode = on
archive_command = 'test ! -f /mnt/wal_archive/%f && cp %p /mnt/wal_archive/%f'

2.2. Dedizierter Replikations-User & Zugriffssteuerung

Erstellen Sie einen unprivilegierten Benutzer, der ausschließlich für das Streaming autorisiert ist:

-- Als postgres Superuser ausführen
CREATE ROLE replicator WITH REPLICATION LOGIN ENCRYPTED PASSWORD 'Secr3t_Repl_Pass_2026!';

Geben Sie die IP-Adresse des Standbys in pg_hba.conf frei:

# Datei: /etc/postgresql/16/main/pg_hba.conf
# TYP  DATENBANK       BENUTZER    ADRESSE             METHODE
host   replication     replicator  192.168.10.20/32    scram-sha-256

Laden Sie die Konfiguration auf dem Primary neu:

sudo systemctl reload postgresql

2.3. Erstellen eines physischen Replikations-Slots

Replikations-Slots garantieren, dass der Primary keine WAL-Dateien löscht oder recycelt, solange der Standby sie noch nicht empfangen hat:

-- Auf dem Primary ausführen
SELECT pg_create_physical_replication_slot('standby_node_1');

Überwachung von Replikations-Slots

Fällt ein Standby dauerhaft aus, sorgt sein Replikations-Slot dafür, dass das pg_wal-Verzeichnis auf dem Primary bis zur vollständigen Festplattenfüllung anwächst. Überwachen Sie Slots stets über SELECT * FROM pg_replication_slots;.


3. Provisionierung des Standby-Knotens

Auf dem Standby-Server (192.168.10.20) wird der lokale PostgreSQL-Dienst gestoppt und ein konsistenter Snapshot des Primarys über pg_basebackup eingespielt.

3.1. Klonen der Instanz via pg_basebackup

# 1. Lokalen PostgreSQL-Dienst stoppen
sudo systemctl stop postgresql

# 2. Bestehendes, leeres Datenverzeichnis leeren
sudo rm -rf /var/lib/postgresql/16/main/*

# 3. Physisches Backup direkt vom Primary abrufen
sudo -u postgres pg_basebackup \
    -h 192.168.10.10 \
    -p 5432 \
    -U replicator \
    -D /var/lib/postgresql/16/main \
    -Fp -Xs -R \
    -S standby_node_1 \
    -v -P

Bedeutung der Parameter:

  • -Fp: Plain-Verzeichnisformat (direkt nutzbare Heap-Dateien).
  • -Xs: Streamt das WAL parallel zum Kopiervorgang, um einen sofort konsistenten Zustand zu erreichen.
  • -R: Erzeugt die Datei standby.signal und schreibt die Verbindungsdaten in postgresql.auto.conf.
  • -S standby_node_1: Verbindet den Standby fest mit dem zuvor angelegten Replikations-Slot.

3.2. Starten des Standbys

sudo systemctl start postgresql
sudo systemctl status postgresql

Prüfen Sie das Logfile zur Verifikation des aktiven WAL-Streams:

sudo tail -f /var/log/postgresql/postgresql-16-main.log
# Erwartete Ausgabe:
# LOG: entering standby mode
# LOG: redo starts at 0/3000028
# LOG: consistent recovery state reached at 0/3000100
# LOG: started streaming WAL from primary at 0/4000000 on timeline 1

4. Replikations-Monitoring & Notfall-Failover

4.1. Replikations-Lag auf dem Primary überwachen

Führen Sie diese administrative Telemetrie-Abfrage auf dem Primary aus, um den Replikationsversatz bytegenau zu berechnen:

SELECT 
    client_addr,
    application_name,
    state,
    sync_state,
    pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS sent_lag_bytes,
    pg_wal_lsn_diff(sent_lsn, write_lsn) AS write_lag_bytes,
    pg_wal_lsn_diff(write_lsn, flush_lsn) AS flush_lag_bytes,
    pg_wal_lsn_diff(flush_lsn, replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;

4.2. Statusprüfung auf dem Standby

-- Prüfen, ob sich der Knoten im Recovery-/Standby-Modus befindet
SELECT pg_is_in_recovery(); -- Liefert true auf Standby, false auf Primary

-- Vergleich empfangener vs. angewendeter Log Sequence Numbers (LSN)
SELECT 
    pg_last_wal_receive_lsn(),
    pg_last_wal_replay_lsn(),
    pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn()) AS pending_replay_bytes;

4.3. Notfall-Promotion zum Primary

Erleidet der Primary-Server einen fatalen Hardwareausfall:

Option A: SQL-Funktion (im Hot-Standby-Betrieb)

SELECT pg_promote();

Option B: Betriebssystem-Befehl (pg_ctl)

sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl promote -D /var/lib/postgresql/16/main

Ablauf der Promotion: 1. PostgreSQL entfernt die Datei standby.signal. 2. Die Engine schreibt einen End-of-Recovery-Eintrag und wechselt auf eine neue Timeline (z. B. Timeline 2). 3. Die Instanz akzeptiert ab sofort Schreib- und Lesezugriffe, ohne dass ein Neustart erforderlich ist.