linux-ubuntu-debian database mysql postgresql replication backup

Database Server Role: MySQL & PostgreSQL (Artikel 036)

Tiefgehende Anleitung zur Verwaltung dedizierter Datenbank-Server. Implementierung von Replikation, Hochverfügbarkeit und professionellen Backup-Strategien.

# Database Server Role: Hochverfügbarkeit & Skalierung

TL;DR / Management Summary Ein dedizierter Datenbank-Server ist das Herz jeder Enterprise-Applikation. Standard-Installationen stoßen bei hoher Last schnell an ihre Grenzen. Wir fokussieren uns auf die Trennung von Schreib- und Leselast (Replikation), die Optimierung der Verbindungen durch Pooling (PgBouncer/ProxySQL) und die Implementierung von konsistenten Backups, die das System nicht blockieren.


# 1. Einführung & Architektur

Die dedizierte Datenbank-Ebene.

Auf dedizierten DB-Servern deaktivieren wir Webserver und andere Dienste, um den gesamten RAM für den Cache (Buffer Pool / Shared Buffers) zu nutzen.

# Replikations-Architektur (Mermaid)

graph TD
    A[Applikation] -->|Write Queries| B[Primary Node / Master]
    B -->|Streaming Replication| C[Replica 1 / Slave]
    B -->|Streaming Replication| D[Replica 2 / Slave]
    A -->|Read Queries| C
    A -->|Read Queries| D

# 2. PostgreSQL Replikation (Streaming)

Daten in Echtzeit spiegeln.

# Schritt 1: Primärer Server (Primary)

Konfigurieren Sie /etc/postgresql/14/main/postgresql.conf:

wal_level = replica
max_wal_senders = 10
hot_standby = on

# Schritt 2: Replica Server (Standby)

Erstellen Sie ein Basis-Backup vom Primary:

pg_basebackup -h <master_ip> -D /var/lib/postgresql/14/main -U replication_user -P -R

Das -R Flag erstellt automatisch die standby.signal Datei.


# 3. MySQL / MariaDB Replikation

Master-Slave Setup.

In MySQL nutzen wir das Binary Log (BinLog), um Änderungen auf die Slaves zu übertragen.

# Beispiel: Master Config

[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = myapp_db

# 4. Day-2 Operations: Backup & Maintenance

Datenverlust ist keine Option.

# Logische Backups (Dump)

Gut für Migrationen, aber langsam bei großen DBs.

# MySQL
mysqldump --single-transaction myapp_db > backup.sql

# PostgreSQL
pg_dump -Fc myapp_db > backup.dump

# Physische Backups (Snapshots)

Viel schneller für große Terabyte-DBs.

  • Proxmox: Nutzen Sie VM-Snapshots (mit QEMU Guest Agent Frozen Filesystem).
  • LVM: Nutzen Sie LVM-Snapshots für Konsistenz (siehe Artikel 020).

# 5. Connection Pooling

Ressourcen sparen.

Jede neue DB-Verbindung kostet RAM und Zeit (Handshake). Ein Pooler hält Verbindungen offen.

  • PgBouncer (für Postgres): Ein Muss ab ca. 50 parallelen Verbindungen.
  • ProxySQL (für MySQL): Erlaubt intelligentes Routing zwischen Master und Slaves.

# 6. Troubleshooting & “War Stories”

Wenn die DB steht.

# Story 1: “Der Replication Lag”

Symptom: Die Webseite zeigt veraltete Daten an, obwohl sie gerade gespeichert wurden. Ursache: Der Slave kommt mit dem Einspielen der Logs nicht hinterher (Replication Lag). Lösung: Prüfen Sie die I/O Performance des Slaves. Oft ist die Disk zu langsam oder das Netzwerk limitiert. In MySQL: SHOW SLAVE STATUS\G.

# Story 2: “Die volle WAL-Partition”

Symptom: Postgres stellt den Betrieb ein (“Disk full”), obwohl das Datenverzeichnis noch Platz hat. Ursache: Die Replikation zum Slave ist abgebrochen. Der Primary behält alle Write-Ahead-Logs (WAL), bis der Slave sie quittiert. Lösung: Slave reparieren oder den Replication Slot manuell löschen, um Platz freizugeben.


# 7. Fazit & Empfehlung

  • Trennung: Nutzen Sie dedizierte Disks/LVs für Logs (/var/log/mysql) und Daten (/var/lib/mysql).
  • Wartung: Führen Sie wöchentlich VACUUM ANALYZE (Postgres) oder OPTIMIZE TABLE (MySQL) durch.
  • Checks: Ein Backup, das nicht regelmäßig getestet wurde (Restore-Drill), existiert nicht!

# Anhang: Cheatsheet

Aufgabe MySQL / MariaDB PostgreSQL
Prozessliste SHOW PROCESSLIST; SELECT * FROM pg_stat_activity;
Index-Größe SHOW TABLE STATUS; \di+
Uptime / Status mysqladmin status pg_isready
Logs live tail -f /var/log/mysql/error.log tail -f /var/log/postgresql/*.log
User listen SELECT user FROM mysql.user; \du
DB Größe SELECT schema_name FROM information_schema.schemata; \l+