TL;DR — Kurzzusammenfassung
Vollstaendige Anleitung zur MySQL-Master-Slave-Replikation fuer Hochverfuegbarkeit: Binary Logs, Slave-Konfiguration, Lag-Monitoring, Failover und ProxySQL.
Die MySQL-Replikation ermoeglicht es einem Server (dem Master), jede Datenaenderung in nahezu Echtzeit an einen oder mehrere Replikat-Server (Slaves) zu uebertragen. Das Ergebnis ist eine Hochverfuegbarkeitsarchitektur, bei der der Lesedatenverkehr auf mehrere Knoten verteilt wird, Backups von einem Slave genommen werden koennen ohne den Master zu belasten, und ein Slave in wenigen Minuten zum Master befoeردert werden kann, wenn der Primaerserver ausfaellt. Dieser Leitfaden deckt die vollstaendige Master-Slave-Replikationseinrichtung auf MySQL 8.0 ab: von der Binary-Log-Konfiguration und der initialen Datensynchronisierung bis hin zu Lag-Monitoring, Wiederherstellung unterbrochener Replikation, Failover-Verfahren und Lese-/Schreibtrennung mit ProxySQL.
Replikationsarchitektur
Die MySQL-Replikation funktioniert durch drei zusammenwirkende Komponenten:
- Binary Log (Binlog) — der Master zeichnet jede bestaettigte Transaktion in einer sequenziellen Log-Datei auf. Es gibt drei Formate:
STATEMENT(zeichnet den SQL-Text auf),ROW(zeichnet die Vorher-/Nachher-Werte veraenderter Zeilen auf) undMIXED(verwendet standardmaessig STATEMENT und wechselt fuer nicht-deterministische Funktionen zu ROW). Verwenden Sie in der Produktion immerROW. - IO-Thread — ein Thread auf dem Slave verbindet sich mit dem Master, liest neue Binary-Log-Ereignisse und schreibt sie in das lokale Relay-Log.
- SQL-Thread — ein zweiter Thread auf dem Slave liest das Relay-Log und spielt die Ereignisse gegen die lokale Datenbank nach, wodurch die Daten synchron gehalten werden.
Replikationsmodi
| Modus | Funktionsweise | Einsatz |
|---|---|---|
| Asynchron (Standard) | Master wartet nicht auf Slave-ACK | Allgemeines HA, Lese-Skalierung |
| Semi-synchron | Master wartet bis mind. ein Slave das Relay-Log geschrieben hat | Finanzdaten, reduziertes Datenverlust-Risiko |
| Group-Replikation | Multi-Master mit Konsensprotokoll (Paxos) | Aktiv-Aktiv, automatisches Failover |
Voraussetzungen
- Zwei Linux-Server mit MySQL 8.0 oder 8.4 (Ubuntu 22.04+ oder RHEL 9+)
- Root- oder Sudo-Zugriff auf beiden Servern
- Netzwerkkonnektivitaet zwischen Master und Slave (Port 3306 offen)
- server-id von Master und Slave muessen eindeutige Ganzzahlen in der gesamten Topologie sein
Schritt 1: Den Master-Server konfigurieren
Bearbeiten Sie die MySQL-Konfiguration auf dem Master:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Fuegen Sie diese Einstellungen in den Abschnitt [mysqld] hinzu oder aendern Sie sie:
[mysqld]
# Eindeutige ID fuer diesen Server — muss auf jedem Knoten unterschiedlich sein
server-id = 1
# Binary-Logging aktivieren — fuer die Replikation erforderlich
log-bin = /var/log/mysql/mysql-bin
binlog-format = ROW
# 7 Tage Binary-Logs aufbewahren
expire_logs_days = 7
# Binlog bei jedem Commit auf Festplatte synchronisieren — verhindert Datenverlust
sync_binlog = 1
# GTID-basierte Replikation (fuer MySQL 8.0+ empfohlen)
gtid_mode = ON
enforce_gtid_consistency = ON
Konfiguration anwenden:
sudo systemctl restart mysql
Binary-Logging verifizieren:
SHOW VARIABLES LIKE 'log_bin';
-- log_bin | ON
SHOW MASTER STATUS\G
-- File: mysql-bin.000003
-- Position: 1573
Schritt 2: Den Replikationsbenutzer erstellen
Erstellen Sie auf dem Master einen dedizierten Benutzer mit nur den fuer die Replikation erforderlichen Berechtigungen:
CREATE USER 'repl'@'192.168.1.102' IDENTIFIED BY 'ReplStr0ng!Pass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.102';
FLUSH PRIVILEGES;
Ersetzen Sie 192.168.1.102 durch die tatsaechliche IP des Slaves. Verwenden Sie niemals % (beliebiger Host) fuer Replikationsbenutzer — schraenken Sie auf IP-Ebene ein.
Schritt 3: Einen konsistenten Snapshot erstellen
Sie benoetigen einen zeitpunktgenauen, konsistenten Snapshot des Masters, um den Slave zu initialisieren. Das Flag --master-data zeichnet die Binary-Log-Position automatisch in der Dump-Datei auf.
# Option A: mysqldump (geeignet fuer Datenbanken unter ~50 GB)
mysqldump -u root -p \
--all-databases \
--master-data=2 \
--single-transaction \
--flush-logs \
--routines \
--triggers \
> /tmp/master_dump.sql
# Option B: Percona XtraBackup (empfohlen fuer grosse Datenbanken, keine Tabellensperren)
xtrabackup --backup --user=root --password=meinpasswort \
--target-dir=/tmp/xtrabackup/
xtrabackup --prepare --target-dir=/tmp/xtrabackup/
Dump auf den Slave uebertragen:
scp /tmp/master_dump.sql benutzer@192.168.1.102:/tmp/
Schritt 4: Den Slave-Server konfigurieren
Bearbeiten Sie auf dem Slave mysqld.cnf:
[mysqld]
# Muss sich von Master und allen anderen Slaves unterscheiden
server-id = 2
# Speicherort des Relay-Logs
relay-log = /var/log/mysql/mysql-relay-bin
# Versehentliche Schreibvorgaenge auf dem Slave verhindern
read_only = 1
super_read_only = 1
# Erforderlich wenn dieser Slave selbst ein Master wird (verkettete Replikation)
log_slave_updates = 1
# GTID-Einstellungen des Masters abgleichen
gtid_mode = ON
enforce_gtid_consistency = ON
sudo systemctl restart mysql
Schritt 5: Snapshot importieren und Replikation starten
Master-Dump auf dem Slave wiederherstellen:
mysql -u root -p < /tmp/master_dump.sql
Slave fuer die Verbindung zum Master konfigurieren. Mit GTID-Modus (empfohlen):
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_AUTO_POSITION = 1;
Ohne GTID (positionsbasiert), Position aus dem Dump-Kommentar ermitteln:
grep "MASTER_LOG_FILE\|MASTER_LOG_POS" /tmp/master_dump.sql | head -5
# -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1573;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_LOG_FILE = 'mysql-bin.000003',
MASTER_LOG_POS = 1573;
Replikation starten:
START SLAVE;
Schritt 6: Replikationsstatus ueberwachen
SHOW SLAVE STATUS\G
Wichtige Felder zur Ueberpruefung:
Slave_IO_Running: Yes -- IO-Thread verbunden und aktiv
Slave_SQL_Running: Yes -- SQL-Thread spielt Ereignisse nach
Seconds_Behind_Master: 0 -- Slave vollstaendig aktuell
Last_IO_Error: (leer) -- keine Verbindungsfehler
Last_SQL_Error: (leer) -- keine Wiedergabefehler
Fuer kontinuierliches Monitoring ueber performance_schema (MySQL 8.0+):
SELECT
CHANNEL_NAME,
SERVICE_STATE,
LAST_ERROR_MESSAGE,
LAST_HEARTBEAT_TIMESTAMP
FROM performance_schema.replication_connection_status;
Replikations-Lag bewaeltigen
Replikations-Lag (wachsendes Seconds_Behind_Master) ist bei intensiven Schreiblasten haeufig:
| Ursache | Loesung |
|---|---|
| Single-threaded SQL-Thread | Parallele Replikations-Worker aktivieren |
| Langsame Abfragen auf dem Slave | Mit SHOW PROCESSLIST identifizieren; optimieren |
| I/O-Engpass auf dem Slave | Relay-Logs auf schnelleren Speicher verschieben |
| Grosse Massentransaktionen | Auf dem Master in kleinere Batches aufteilen |
| Netzwerklatenz | Master und Slaves im selben Rechenzentrum platzieren |
Parallele Replikation aktivieren (MySQL 8.0):
STOP SLAVE SQL_THREAD;
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
START SLAVE SQL_THREAD;
Unterbrochene Replikation reparieren
Wenn Slave_SQL_Running: No in SHOW SLAVE STATUS erscheint:
Eine fehlerhafte Transaktion ueberspringen
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;
SHOW SLAVE STATUS\G
Per GTID ueberspringen (sicherer im GTID-Modus)
STOP SLAVE;
-- GTID aus der Last_SQL_Error-Meldung ersetzen
SET GTID_NEXT = 'a1b2c3d4-1111-2222-3333-444444444444:1234';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;
Vollstaendige Neusynchronisierung vom Master
STOP SLAVE;
RESET SLAVE ALL;
-- Snapshot ab Schritt 3 erneut erstellen und neu konfigurieren
Failover: Slave zum Master befoerdern
Wenn der Master ausfaellt und ein Slave befoerdert werden muss:
-- Auf dem zu befoerdernden Slave:
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 0
STOP SLAVE;
RESET SLAVE ALL;
-- Nur-Lese-Modus deaktivieren — dieser Server ist jetzt der Master
SET GLOBAL read_only = 0;
SET GLOBAL super_read_only = 0;
Verbindungsstrings der Anwendung auf die neue Master-IP aktualisieren und verbleibende Slaves neu konfigurieren:
-- Auf verbleibenden Slaves:
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.102',
MASTER_AUTO_POSITION = 1;
START SLAVE;
Schritt 7: ProxySQL fuer Lese-/Schreibtrennung
ProxySQL sitzt zwischen Anwendung und MySQL, leitet Schreibvorgaenge zum Master und Lesevorgaenge zu Slaves transparent weiter.
# ProxySQL installieren (Ubuntu)
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | sudo apt-key add -
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.x/$(lsb_release -sc)/ ./" \
| sudo tee /etc/apt/sources.list.d/proxysql.list
sudo apt update && sudo apt install proxysql
sudo systemctl enable --now proxysql
Konfiguration ueber die ProxySQL-Admin-Schnittstelle (Port 6032):
-- Server hinzufuegen: Hostgroup 0 = Schreiben (Master), Hostgroup 1 = Lesen (Slave)
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES
(0, '192.168.1.101', 3306),
(1, '192.168.1.102', 3306);
-- Anwendungsbenutzer hinzufuegen
INSERT INTO mysql_users (username, password, default_hostgroup) VALUES
('appuser', 'AppPass123!', 0);
-- SELECT-Abfragen zur Lese-Hostgroup routen
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES
(1, 1, '^SELECT.*', 1, 1);
-- Aenderungen anwenden und speichern
LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;
Die Anwendung verbindet sich mit ProxySQL auf Port 6033 und das gesamte Routing wird transparent verwaltet.
Vergleich: MySQL-Replikation vs. Alternativen
| Loesung | Architektur | Failover | Schreib-Skalierung | Komplexitaet |
|---|---|---|---|---|
| MySQL-Replikation | Master + Slaves | Manuell oder MHA | Nein (ein Master) | Gering |
| MySQL Group-Replikation | Multi-Master Paxos | Automatisch | Begrenzt | Mittel |
| Galera Cluster (MariaDB) | Synchroner Multi-Master | Automatisch | Ja | Mittel |
| Vitess | MySQL mit Sharding | Automatisch | Ja (Sharding) | Hoch |
| PlanetScale | Verwaltetes Vitess | Verwaltet | Ja | Gering (verwaltet) |
| PostgreSQL Streaming | Primaer + Standbys | Patroni/manuell | Nein | Gering-Mittel |
Besonderheiten und Fallstricke
- server-id muss global eindeutig sein auf allen Knoten — zwei Knoten mit gleicher ID korrumpieren die Replikation still und leise
read_only=1blockiert keine SUPER-Benutzer — verwenden Siesuper_read_only=1um den Slave vollstaendig zu sperren- Grosse Transaktionen blockieren den IO-Thread — verwenden Sie
pt-online-schema-changefuer grosse DDL-Operationen - Zeitzonenunterschiede verursachen Replikationsfehler — setzen Sie
default-time-zone='+00:00'auf allen Knoten
Zusammenfassung
- MySQL-Replikation verwendet Binary-Logs, IO-Threads und SQL-Threads um Slaves synchron zu halten
- Verwenden Sie
binlog-format=ROW,sync_binlog=1und GTID-Modus (gtid_mode=ON) in der Produktion - Ueberwachen Sie
Slave_IO_Running,Slave_SQL_RunningundSeconds_Behind_Masterkontinuierlich - Aktivieren Sie parallele Replikations-Worker um Lag bei intensiven Schreiblasten zu reduzieren
- Verwenden Sie
RESET SLAVE ALLfuer eine saubere Neukonfiguration statt zu versuchen einen defekten Zustand zu flicken - ProxySQL leitet transparent Lesevorgaenge zu Slaves und Schreibvorgaenge zum Master