asynchron vs. semi-synchron in MySQL
MySQL-Replikation entscheidet darüber, wie viele Transaktionen im Fehlerfall verloren gehen können und wie stark eine Anwendung auf veraltete Lesedaten trifft. Wer den Unterschied zwischen asynchroner und semi-synchroner Replikation, Binlog-Verarbeitung und Replication Lag versteht, kann die Konfiguration gezielt auf Konsistenzanforderungen statt auf Standardwerte auslegen.
Inhaltsverzeichnis
- 1. Was MySQL-Replikation eigentlich löst
- 2. Wie asynchrone Replikation intern funktioniert
- 3. Semi-synchrone Replikation: ACK vor Commit
- 4. Replication Lag: Ursachen und Messung
- 5. GTID-basierte Replikation aktivieren
- 6. Eine Replica Schritt für Schritt einrichten
- 7. Multi-threaded Replication und Parallelisierung
- 8. Monitoring mit SHOW REPLICA STATUS
- 9. Asynchron vs. semi-synchron im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Was MySQL-Replikation eigentlich löst
MySQL-Replikation kopiert Datenänderungen von einer Quelle auf einen oder mehrere Replicas und löst damit mehrere unabhängige Probleme gleichzeitig: Ausfallsicherheit durch eine warme Kopie der Daten, Lastverteilung durch zusätzliche Leseserver und geografische Nähe durch Replicas in anderen Regionen. Ohne Replikation liegt jede Schreib- und Leseoperation auf einem einzigen Server, dessen Ausfall die gesamte Anwendung lahmlegt und dessen Kapazität die Obergrenze für die gesamte Lesekapazität darstellt.
Der entscheidende Designfaktor bei MySQL-Replikation ist die Frage, wie ein Commit auf der Quelle mit der Übertragung auf die Replica zusammenhängt. Läuft die Übertragung vollständig unabhängig vom Commit, spricht man von asynchroner Replikation. Wartet die Quelle auf eine Bestätigung, bevor der Commit als abgeschlossen gilt, handelt es sich um semi-synchrone Replikation. Dieser Unterschied bestimmt direkt, wie viele Transaktionen im schlimmsten Fall verloren gehen können, wenn die Quelle nach einem Commit sofort ausfällt.
2. Wie asynchrone Replikation intern funktioniert
Bei der klassischen asynchronen MySQL-Replikation schreibt die Quelle jede Datenänderung zunächst in ihr Binary Log, kurz Binlog. Ein Commit auf der Quelle gilt als abgeschlossen, sobald die Transaktion im InnoDB Redo Log und im Binlog persistiert ist, unabhängig davon, ob eine Replica die Änderung bereits erhalten hat. Auf der Replica liest ein IO-Thread kontinuierlich den Binlog-Stream der Quelle und schreibt die Ereignisse in ein lokales Relay Log. Ein separater SQL-Thread, beziehungsweise bei aktivierter Parallelisierung mehrere Worker-Threads, liest das Relay Log und wendet die Änderungen auf die eigenen Tabellen an.
Diese Entkopplung von IO- und Anwendungsschritt ist der Grund, warum asynchrone Replikation performant skaliert: Die Quelle wird durch langsame Replicas nicht ausgebremst, und Netzwerklatenz zur Replica hat keinen direkten Einfluss auf die Commit-Latenz auf der Quelle. Der Preis dafür ist ein potenzieller Datenverlust im Failover-Fall. Fällt die Quelle unmittelbar nach einem Commit aus, bevor der IO-Thread der Replica das entsprechende Binlog-Event überhaupt gelesen hat, existiert diese Transaktion ausschließlich auf der ausgefallenen Quelle und ist bei einem Failover auf die Replica verloren.
Für die meisten Lesezugriffe und für nicht kritische Reporting-Workloads ist dieses Risiko akzeptabel, weil asynchrone MySQL-Replikation deutlich geringere Latenz auf der Schreibseite erzeugt als jede synchrone Variante. Für Finanztransaktionen, Bestellabschlüsse oder andere Vorgänge, bei denen ein verlorener Commit direkten Geschäftsschaden verursacht, reicht asynchrone Replikation allein oft nicht aus.
# my.cnf on the source: minimal configuration for asynchronous replication
[mysqld]
server-id = 1
log_bin = /var/log/mysql/binlog
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
sync_binlog = 1
# my.cnf on the replica: read-only, independent server-id
[mysqld]
server-id = 2
relay_log = /var/log/mysql/relaylog
read_only = ON
super_read_only = ON
gtid_mode = ON
enforce_gtid_consistency = ON
# Check IO and SQL thread lag independently after START REPLICA
SHOW STATUS LIKE 'Slave_running';
SELECT service_state, remaining_delay
FROM performance_schema.replication_applier_status_by_worker;
3. Semi-synchrone Replikation: ACK vor Commit
Semi-synchrone MySQL-Replikation schließt genau diese Lücke, ohne die volle Latenz einer synchronen Multi-Master-Lösung zu erzeugen. Bei aktiviertem semi-sync Plugin wartet die Quelle nach dem Schreiben ins Binlog auf eine Bestätigung von mindestens einer Replica, dass das Binlog-Event im Relay Log angekommen ist, bevor der Commit dem Client als erfolgreich zurückgemeldet wird. Wichtig ist die Präzisierung: Die Replica muss das Event nur empfangen und persistiert haben, nicht zwingend bereits auf die Tabellen angewendet haben. Das unterscheidet semi-synchrone Replikation von echter synchroner Replikation, bei der auch die Anwendung der Änderung abgewartet würde.
Praktisch wird semi-synchrone Replikation über die Plugins rpl_semi_sync_source und rpl_semi_sync_replica aktiviert, in älteren Versionen unter den Namen rpl_semi_sync_master und rpl_semi_sync_slave. Der Parameter rpl_semi_sync_source_timeout definiert, wie lange die Quelle auf die Bestätigung wartet, bevor sie automatisch in den asynchronen Modus zurückfällt. Dieser Fallback ist entscheidend für die Verfügbarkeit: Ohne ihn würde ein Ausfall aller Replicas auch die Quelle blockieren, weil kein Commit mehr bestätigt werden könnte.
-- Semi-synchronous replication: install plugins on source and replica
-- Run on the source server
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = 1;
SET GLOBAL rpl_semi_sync_source_timeout = 10000; -- milliseconds before fallback to async
-- Run on every replica
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = 1;
-- Restart the replication IO thread so the new setting takes effect
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;
-- Verify semi-sync status on the source
SHOW STATUS LIKE 'Rpl_semi_sync_source_status';
SHOW STATUS LIKE 'Rpl_semi_sync_source_clients';
In der Praxis kombinieren viele Setups semi-synchrone MySQL-Replikation mit mindestens einer geografisch entfernten Replica, damit ein regionaler Ausfall der Quelle nicht automatisch auch die einzige Bestätigungsquelle mitreißt. Der Timeout sollte niedrig genug sein, um bei einem echten Replica-Ausfall nicht die Schreiblast der Quelle zu blockieren, aber hoch genug, um normale Netzwerkschwankungen nicht als Ausfall zu interpretieren.
4. Replication Lag: Ursachen und Messung
Replication Lag beschreibt die zeitliche Verzögerung zwischen einem Commit auf der Quelle und dem Sichtbarwerden derselben Änderung auf der Replica. Bei asynchroner MySQL-Replikation ist ein gewisser Lag immer vorhanden, weil die Anwendung der Änderungen nachgelagert erfolgt. Problematisch wird es, wenn der Lag unkontrolliert wächst, etwa weil die Replica-Hardware schwächer als die Quelle ist, weil einzelne Transaktionen sehr große Datenmengen betreffen, oder weil der SQL-Thread bei einer schreibintensiven Tabelle ohne Parallelisierung nicht mit dem Schreibvolumen der Quelle mithalten kann.
Der klassische Indikator Seconds_Behind_Source, in älteren Versionen Seconds_Behind_Master, aus SHOW REPLICA STATUS ist ein nützlicher, aber unvollständiger Wert. Er misst die Differenz zwischen dem Zeitstempel des zuletzt verarbeiteten Events und der aktuellen Systemzeit der Replica, sagt aber nichts darüber aus, wie viele Events der IO-Thread bereits empfangen, aber der SQL-Thread noch nicht angewendet hat. Präziser ist der Vergleich der GTID-Sets zwischen Quelle und Replica oder die Auswertung von performance_schema.replication_applier_status_by_worker, die pro Worker-Thread den Verarbeitungsstand zeigt.
Replication Lag hat direkte Konsequenzen für Anwendungen, die Lesezugriffe auf Replicas verteilen: Ein Nutzer, der unmittelbar nach dem Schreiben liest, kann veraltete Daten sehen, wenn der Read auf eine Replica mit spürbarem Lag geroutet wird. Deshalb gehört Lag-Monitoring in jedes Setup, das Replicas produktiv für Leseoperationen nutzt, nicht nur als reine Backup-Kopie.
5. GTID-basierte Replikation aktivieren
Global Transaction Identifiers, kurz GTID, ersetzen die traditionelle positionsbasierte Replikation mit Binlog-Dateiname und Offset durch eindeutige, serverübergreifende Transaktions-IDs. Jede Transaktion erhält beim Commit eine GTID nach dem Schema server_uuid:transaction_number, die über alle Server im Replikationsverbund eindeutig bleibt. Der große Vorteil gegenüber positionsbasierter MySQL-Replikation: Ein Failover auf eine andere Replica erfordert kein manuelles Suchen der korrekten Binlog-Position, weil jeder Server anhand der bereits ausgeführten GTID-Menge selbst erkennt, ab welcher Transaktion er weiterreplizieren muss.
GTID wird über gtid_mode = ON und enforce_gtid_consistency = ON in der Serverkonfiguration aktiviert. Der zweite Parameter verbietet Statements, die mit GTID-basierter Replikation nicht sicher zu handhaben sind, etwa nicht-transaktionale Änderungen gemeinsam mit transaktionalen in einer Anweisung. Nach der Migration auf GTID entfällt bei einem Replica-Wechsel das fehleranfällige manuelle Ablesen von File und Position aus SHOW MASTER STATUS, stattdessen genügt CHANGE REPLICATION SOURCE TO ... SOURCE_AUTO_POSITION = 1.
6. Eine Replica Schritt für Schritt einrichten
Der Aufbau einer neuen Replica folgt einem festen Ablauf: Zunächst wird auf der Quelle ein dedizierter Replikationsbenutzer mit dem Recht REPLICATION SLAVE angelegt, danach ein konsistentes Backup der Quelle erstellt, etwa mit mysqldump --single-transaction --source-data=2 oder mit Percona XtraBackup für größere Datenbanken ohne Locking. Nach dem Einspielen des Backups auf dem neuen Server wird die Replikation mit CHANGE REPLICATION SOURCE TO konfiguriert und mit START REPLICA gestartet.
-- On the source: create a dedicated replication user
CREATE USER 'repl'@'10.0.%' IDENTIFIED BY 'strong-password-here';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.%';
FLUSH PRIVILEGES;
-- On the source: enable binary logging and GTID in my.cnf
-- [mysqld]
-- server-id = 1
-- log_bin = /var/log/mysql/binlog
-- binlog_format = ROW
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- On the new replica: point it at the source using GTID auto-positioning
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'db-primary.internal',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'strong-password-here',
SOURCE_AUTO_POSITION = 1,
SOURCE_SSL = 1;
START REPLICA;
SHOW REPLICA STATUS\G
Nach dem Start prüft man Replica_IO_Running und Replica_SQL_Running, beide müssen Yes anzeigen, damit die MySQL-Replikation vollständig funktioniert. Ein häufiger Fehler in der Praxis ist ein zu klein dimensioniertes Backup-Fenster: Wird das Backup nicht mit konsistentem Snapshot erstellt, etwa ohne --single-transaction, entstehen auf der neuen Replica Inkonsistenzen, die erst bei der ersten abweichenden Abfrage auffallen.
7. Multi-threaded Replication und Parallelisierung
In älteren MySQL-Versionen wendete ein einzelner SQL-Thread alle Änderungen sequenziell an, was bei schreibintensiven Quellen mit vielen parallelen Transaktionen regelmäßig zu wachsendem Lag führte. Multi-threaded Replication, kurz MTS, parallelisiert die Anwendung über mehrere Worker-Threads, gesteuert über replica_parallel_workers. Die Parallelisierungsstrategie replica_parallel_type = LOGICAL_CLOCK nutzt Informationen aus der Gruppen-Commit-Logik der Quelle, um Transaktionen, die dort gleichzeitig committet wurden, auch auf der Replica parallel anzuwenden, ohne die Konsistenz zu gefährden.
Die Parallelisierung bringt vor allem bei Workloads mit vielen unabhängigen Tabellen oder Schemas signifikante Vorteile für die MySQL-Replikation. Bei Workloads, die überwiegend eine einzelne, stark frequentierte Tabelle betreffen, ist der Parallelisierungsgewinn begrenzt, weil viele Transaktionen ohnehin serialisiert werden müssen, um Konflikte zu vermeiden. In solchen Fällen hilft eher eine Reduktion der Transaktionsgröße auf der Quelle oder ein Wechsel des Binlog-Formats auf ROW, das granularere Parallelisierung erlaubt als STATEMENT.
-- Enable multi-threaded replication with 8 parallel worker threads
SET GLOBAL replica_parallel_workers = 8;
SET GLOBAL replica_parallel_type = 'LOGICAL_CLOCK';
SET GLOBAL replica_preserve_commit_order = ON;
STOP REPLICA;
START REPLICA;
-- Inspect per-worker progress and detect a lagging worker thread
SELECT worker_id, service_state, last_applied_transaction,
apply_time_period
FROM performance_schema.replication_applier_status_by_worker
ORDER BY worker_id;
8. Monitoring mit SHOW REPLICA STATUS
Der Befehl SHOW REPLICA STATUS\G bleibt trotz moderner Performance-Schema-Tabellen das erste Diagnosewerkzeug für MySQL-Replikation. Wichtige Felder sind Replica_IO_State, das den aktuellen Zustand des IO-Threads beschreibt, Last_IO_Error und Last_SQL_Error für Fehlermeldungen, sowie Retrieved_Gtid_Set und Executed_Gtid_Set, deren Vergleich zeigt, wie viele empfangene Transaktionen noch nicht angewendet wurden.
-- Typical (shortened) output of SHOW REPLICA STATUS on a healthy replica
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: db-primary.internal
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 0
Last_IO_Error:
Last_SQL_Error:
Retrieved_Gtid_Set: a1b2c3d4-0000-0000-0000-000000000001:1-98421
Executed_Gtid_Set: a1b2c3d4-0000-0000-0000-000000000001:1-98421
-- Compare GTID sets programmatically to detect a stuck applier
SELECT GTID_SUBTRACT(
@@GLOBAL.gtid_executed,
(SELECT VARIABLE_VALUE FROM performance_schema.global_variables
WHERE VARIABLE_NAME = 'gtid_executed')
) AS pending_transactions;
Für dauerhaftes Monitoring reicht ein manueller Blick auf SHOW REPLICA STATUS nicht aus. Produktive Setups exportieren Seconds_Behind_Source, den semi-sync Bestätigungsstatus und die Anzahl aktiver Replica-Verbindungen regelmäßig in ein Monitoring-System wie Prometheus über den MySQL Exporter, damit Lag-Spitzen und ausgefallene Replikationskanäle automatisiert Alarme auslösen, statt erst bei einer Kundenbeschwerde aufzufallen.
9. Asynchron vs. semi-synchron im Vergleich
Die Wahl zwischen asynchroner und semi-synchroner MySQL-Replikation ist eine Abwägung zwischen Schreiblatenz und Datensicherheit im Failover-Fall. Die folgende Tabelle fasst die wichtigsten Unterschiede für die Entscheidung in der Praxis zusammen.
| Kriterium | Asynchrone Replikation | Semi-synchrone Replikation |
|---|---|---|
| Commit-Latenz | Minimal, keine Wartezeit auf Replicas | Erhöht um Netzwerk-Roundtrip zur schnellsten Replica |
| Datenverlustrisiko bei Failover | Möglich, letzte Transaktionen können fehlen | Deutlich reduziert, sofern mindestens ein ACK vorlag |
| Verhalten bei Replica-Ausfall | Quelle läuft unbeeinträchtigt weiter | Fallback auf asynchron nach Timeout, dann wie links |
| Konfigurationsaufwand | Gering, Standardverhalten von MySQL | Plugin-Installation und Timeout-Tuning nötig |
| Typischer Einsatz | Reporting-Replicas, geografisch entfernte Kopien | Finanzdaten, Bestellsysteme, kritische OLTP-Workloads |
In der Praxis setzen viele Betreiber ein hybrides Modell ein: eine oder zwei lokale Replicas laufen semi-synchron, um Datenverlust im lokalen Rechenzentrum zu minimieren, während geografisch entfernte Replicas rein asynchron angebunden sind, um die Commit-Latenz nicht durch Interkontinental-Latenz zu belasten. Diese Kombination nutzt die Stärken beider Modi der MySQL-Replikation, ohne die jeweiligen Schwächen vollständig in Kauf zu nehmen.
Mironsoft
MySQL-Replikation, Hochverfügbarkeit und Datenbankarchitektur
Replikation, die im Ernstfall wirklich hält?
Wir analysieren bestehende MySQL-Replikationstopologien, konfigurieren semi-synchrone Absicherung dort, wo es zählt, und richten Monitoring für Replication Lag ein, bevor es zum Problem wird.
Replikations-Audit
Analyse bestehender Topologien auf Datenverlustrisiko und Lag-Verhalten
GTID-Migration
Umstellung von positionsbasierter auf GTID-basierte Replikation
Monitoring-Setup
Lag-Alarme und semi-sync Status in Prometheus und Grafana integrieren
10. Zusammenfassung
Die Wahl zwischen asynchroner und semi-synchroner MySQL-Replikation ist keine reine Konfigurationsfrage, sondern eine bewusste Entscheidung über akzeptablen Datenverlust im Failover-Fall gegenüber zusätzlicher Commit-Latenz. Asynchrone Replikation ist der richtige Standard für Reporting-Replicas und geografisch entfernte Kopien, semi-synchrone Replikation gehört dort hin, wo ein verlorener Commit echten Schaden anrichtet. GTID vereinfacht Failover und Replica-Aufbau erheblich gegenüber der klassischen positionsbasierten Replikation.
Replication Lag ist kein statischer Wert, sondern muss kontinuierlich überwacht werden, insbesondere wenn Replicas für Leseoperationen in der Anwendung genutzt werden. Multi-threaded Replication reduziert Lag bei geeigneten Workloads deutlich, ersetzt aber kein sauberes Monitoring über SHOW REPLICA STATUS und Performance-Schema-Tabellen. Wer diese Grundlagen der MySQL-Replikation beherrscht, kann Topologien gezielt für die tatsächlichen Konsistenzanforderungen der Anwendung auslegen, statt sich auf Standardwerte zu verlassen.
MySQL-Replikation: Das Wichtigste auf einen Blick
Asynchron
Minimale Commit-Latenz, aber potenzieller Datenverlust bei Failover unmittelbar nach einem Commit.
Semi-synchron
Wartet auf ein ACK von mindestens einer Replica vor dem Commit, mit Fallback auf async nach Timeout.
GTID
Eindeutige Transaktions-IDs vereinfachen Failover und Replica-Aufbau mit SOURCE_AUTO_POSITION.
Monitoring
Seconds_Behind_Source, GTID-Sets und semi-sync Status regelmäßig in Prometheus exportieren.