Schemaänderungen über Binlog-Streaming statt über Trigger
Trigger-basierte Werkzeuge wie pt-online-schema-change lösen viele Probleme, erzeugen aber auf jeder einzelnen Schreiboperation zusätzlichen synchronen Aufwand. gh-ost, von GitHub entwickelt, verfolgt einen grundlegend anderen Ansatz: Es liest Änderungen asynchron aus dem MySQL-Binärlog, genau wie ein regulärer Replica-Server, und wendet sie auf eine Ghost-Tabelle an. Bei Tabellen mit sehr hoher, konstanter Schreiblast macht dieser Unterschied den entscheidenden Unterschied zwischen einer unbemerkten Migration und einer, die den produktiven Betrieb spürbar verlangsamt.
Inhaltsverzeichnis
- 1. Vom Trigger- zum Binlog-Ansatz: die Grundidee von gh-ost
- 2. Wie das Binlog-Streaming als Change-Data-Capture funktioniert
- 3. Architekturvergleich zu pt-online-schema-change
- 4. Voraussetzungen: Binlog-Format, GTID und Berechtigungen
- 5. Der praktische Workflow: Test-Run, Dry-Run, Execute
- 6. Throttling und der interaktive Steuerkanal
- 7. Der Cut-Over-Moment im Detail
- 8. Grenzen und Stolperfallen
- 9. Wann gh-ost gegenüber pt-osc oder nativem DDL die richtige Wahl ist
- 10. Zusammenfassung
- 11. FAQ
1. Vom Trigger- zum Binlog-Ansatz: die Grundidee von gh-ost
gh-ost, kurz für GitHub's Online Schema Change, wurde bei GitHub entwickelt, nachdem pt-online-schema-change auf sehr großen, schreibintensiven Tabellen wiederholt an Grenzen stieß. Statt wie pt-osc synchrone Trigger auf der Originaltabelle zu installieren, verhält sich gh-ost gegenüber dem MySQL-Server wie ein ganz normaler Replica: es baut eine reguläre Replikationsverbindung auf und liest darüber den Strom aller Änderungsereignisse aus dem Binärlog.
Diese Änderungsereignisse wendet gh-ost anschließend asynchron auf eine separate Ghost-Tabelle an, parallel zum eigentlichen Kopiervorgang der bestehenden Daten. Der entscheidende Vorteil: die ursprüngliche Anwendung bemerkt von diesem Vorgang praktisch nichts, weil keine zusätzlichen Trigger auf der Originaltabelle laufen und jede reguläre Schreiboperation exakt so schnell bleibt wie vor der Migration.
2. Wie das Binlog-Streaming als Change-Data-Capture funktioniert
MySQL schreibt bei zeilenbasierter Replikation, also binlog_format=ROW, für jede geänderte Zeile ein vollständiges Vorher- und Nachher-Abbild in den Binärlog. gh-ost verbindet sich über das normale Replikationsprotokoll, meldet sich als Replica mit eigener Server-ID an und erhält darüber denselben Ereignisstrom, den auch ein regulärer Replica-Server empfangen würde. Aus diesem Strom filtert gh-ost gezielt nur die Ereignisse heraus, die die zu migrierende Tabelle betreffen.
Jedes gefilterte Ereignis wird intern in eine entsprechende Anwendung auf die Ghost-Tabelle übersetzt: ein Insert-Ereignis wird zu einem Insert, ein Update-Ereignis zu einem Update, ein Delete-Ereignis zu einem Delete. Weil dieser Prozess vollständig asynchron zur eigentlichen Anwendungsschreiboperation abläuft, entsteht dabei keinerlei zusätzliche Latenz für die Anwendung selbst, allenfalls eine geringe Verzögerung, bis eine Änderung auch in der Ghost-Tabelle ankommt.
# gh-ost benoetigt binlog_format=ROW als Voraussetzung
mysql -e "SHOW VARIABLES LIKE 'binlog_format';"
# Dry run gegen die Zieltabelle, keine Änderung an Produktionsdaten
gh-ost --host=db-primary.internal --database=magento --table=catalog_product_entity --alter="ADD INDEX idx_sku_type (sku, type_id)" --dry-run
3. Architekturvergleich zu pt-online-schema-change
Der Kernunterschied zwischen gh-ost und pt-online-schema-change liegt in der Frage, wo die zusätzliche Arbeit anfällt. Bei pt-osc entsteht sie synchron in derselben Transaktion wie jede Anwendungsschreiboperation, weil ein Trigger vor dem eigentlichen Commit ausgeführt werden muss. Bei gh-ost entsteht sie vollständig entkoppelt, in einem separaten Prozess, der den Binärlog irgendwann nach dem Commit ausliest und verarbeitet.
Diese Entkopplung bedeutet in der Praxis: eine Tabelle mit mehreren tausend Schreiboperationen pro Sekunde, etwa eine Sitzungs- oder Ereignis-Log-Tabelle in einem stark frequentierten Magento-Shop, spürt bei gh-ost keinen zusätzlichen Schreib-Overhead pro Anfrage. Der Preis dafür ist eine höhere Komplexität im Werkzeug selbst und eine gewisse, meist geringe Verzögerung, bis Änderungen aus dem Binärlog tatsächlich in der Ghost-Tabelle ankommen.
4. Voraussetzungen: Binlog-Format, GTID und Berechtigungen
Zwingende Voraussetzung ist binlog_format=ROW, statement- oder mixed-basierte Replikation reicht nicht aus, da gh-ost auf die vollständigen Vorher-Nachher-Zeilenabbilder angewiesen ist. Für den Datenbankbenutzer, mit dem gh-ost sich verbindet, sind mindestens die Rechte REPLICATION SLAVE und REPLICATION CLIENT nötig, zusätzlich die üblichen DML- und DDL-Rechte auf der Zieldatenbank.
Vor jedem produktiven Einsatz empfiehlt sich zusätzlich ein Testlauf über --test-on-replica, bei dem gh-ost die komplette Migration auf einem dedizierten Replica durchführt, dort die Replikation anhält und die Ergebnisse zwischen Original- und Ghost-Tabelle automatisch auf Konsistenz vergleicht, ganz ohne Auswirkung auf den produktiven Primärserver.
5. Der praktische Workflow: Test-Run, Dry-Run, Execute
Ein sinnvoller Ablauf beginnt mit einem --test-on-replica-Lauf gegen einen dedizierten Replica, gefolgt von einem --dry-run gegen den Primärserver, der alle Prüfungen durchführt, aber ohne tatsächliche Migration. Erst danach folgt der reale Lauf mit --execute, idealerweise außerhalb der Hauptlastzeiten, auch wenn gh-ost dank Throttling grundsätzlich auch während normaler Lastzeiten sicher laufen kann.
Während der Ausführung gibt gh-ost fortlaufend Statusinformationen aus: kopierte Zeilen, geschätzte Restlaufzeit, aktueller Durchsatz und aktuelle Replikationsverzögerung. Diese Ausgabe lässt sich zusätzlich über eine Unix-Socket-Schnittstelle interaktiv abfragen, was insbesondere bei Migrationen ohne direkten Terminalzugriff, etwa gestartet über einen CI-Job, wertvoll ist.
# Test-Run auf einem dedizierten Replica, keine Auswirkung auf den Primaerserver
gh-ost --host=db-replica.internal --database=magento --table=sales_order_grid --alter="ADD COLUMN priority TINYINT DEFAULT 0" --test-on-replica
# Produktiver Lauf mit interaktivem Steuerkanal über Unix Socket
gh-ost --host=db-primary.internal --database=magento --table=sales_order_grid --alter="ADD COLUMN priority TINYINT DEFAULT 0" --serve-socket-file=/tmp/gh-ost.sales_order_grid.sock --execute
6. Throttling und der interaktive Steuerkanal
gh-ost überwacht während der gesamten Migration kontinuierlich die Replikationsverzögerung auf allen konfigurierten Replicas. Überschreitet die Verzögerung den mit --max-lag-millis definierten Schwellenwert, drosselt gh-ost den Kopiervorgang automatisch, bis die Replicas wieder aufgeholt haben. Zusätzlich lässt sich über --nice-ratio ein bewusster Verlangsamungsfaktor konfigurieren, der auch ohne konkrete Lag-Überschreitung dauerhaft Rücksicht auf die reguläre Anwendungslast nimmt.
Über die genannte Unix-Socket-Schnittstelle lässt sich eine laufende Migration jederzeit manuell drosseln, mit dem Befehl throttle, oder wieder beschleunigen, mit no-throttle, ohne den Prozess neu starten zu müssen. Das ist besonders während unerwarteter Lastspitzen im Tagesgeschäft wertvoll, etwa bei einer plötzlichen Kampagne mit ungewöhnlich hohem Bestellaufkommen.
7. Der Cut-Over-Moment im Detail
Zum Abschluss der Migration bietet gh-ost zwei Cut-Over-Strategien. Der Standard, --cut-over=atomic, nutzt einen speziellen Lock-Mechanismus, der sicherstellt, dass während des Umschaltens keine Schreibzugriffe auf die alte Tabelle verloren gehen, indem kurzfristig alle Schreiboperationen blockiert werden, während die letzten ausstehenden Binlog-Ereignisse noch angewendet werden. Diese Blockade dauert typischerweise nur Sekundenbruchteile bis wenige Sekunden.
Die Alternative --cut-over=two-step arbeitet konservativer mit zwei getrennten Schritten und ist tolerant gegenüber bestimmten Verbindungsabbrüchen während des Umschaltens, benötigt dafür aber insgesamt etwas mehr Zeit. Für die meisten Magento-Migrationen ist der atomare Cut-Over die bevorzugte Wahl, solange die Netzwerkverbindung zwischen gh-ost-Prozess und Datenbankserver stabil ist.
8. Grenzen und Stolperfallen
Die wichtigste Einschränkung von gh-ost betrifft Fremdschlüssel: das Werkzeug unterstützt Tabellen mit Fremdschlüsselbeziehungen standardmäßig überhaupt nicht und bricht bei deren Erkennung ab, sofern nicht explizit --discard-foreign-keys gesetzt wird, was die Fremdschlüssel auf der neuen Tabelle vollständig entfernt. Bei stark vernetzten Magento-Tabellen mit vielen referenzierenden Fremdschlüsseln ist das ein erheblicher praktischer Unterschied zu pt-online-schema-change, das Fremdschlüssel zumindest konfigurierbar handhabt.
Weitere Einschränkungen: eine Tabelle benötigt zwingend einen Primärschlüssel oder mindestens einen eindeutigen, nicht-nullbaren Index als Grundlage für den Kopiervorgang, und bei extrem häufig geänderten Zeilen während der Migration kann sich die Restlaufzeit verlängern, weil dieselben Zeilen mehrfach über den Binärlog nachgezogen werden müssen. Auch Trigger auf der Originaltabelle, die selbst wieder DDL-relevante Nebeneffekte haben, sind mit dem Ghost-Ansatz nicht kompatibel.
-- Fremdschluessel-Erkennung vor der Migration pruefen
SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'catalog_product_entity';
9. Wann gh-ost gegenüber pt-osc oder nativem DDL die richtige Wahl ist
gh-ost spielt seine Stärken vor allem bei Tabellen mit sehr hoher, konstanter Schreiblast aus, etwa quote_item, sales_order_grid oder benutzerdefinierten Log-Tabellen in stark frequentierten Magento-Shops, bei denen der Trigger-Overhead von pt-online-schema-change tatsächlich spürbar würde. Auch wenn eine feingranulare Steuerung über Throttling und ein besonders sicherer, getesteter Cut-Over-Mechanismus im Vordergrund stehen, ist gh-ost häufig die bevorzugte Wahl.
Bei Tabellen mit Fremdschlüsseln, bei denen ein vollständiges Entfernen der Referenzen keine Option ist, bleibt pt-online-schema-change dagegen häufig die praktikablere Lösung. Und für alle Operationen, die native ALGORITHM=INSTANT- oder INPLACE-Unterstützung besitzen und keine Kapazitätsprobleme mit dem Row-Log erwarten lassen, bleibt das eingebaute Online DDL von MySQL selbst weiterhin die einfachste und schnellste Option.
| Kriterium | gh-ost | pt-online-schema-change |
|---|---|---|
| Change-Capture-Mechanismus | Asynchrones Binlog-Streaming | Synchrone Trigger |
| Schreib-Overhead auf der Originaltabelle | Praktisch keiner | Ein zusätzlicher Trigger-Aufwand pro Schreibzugriff |
| Fremdschlüssel-Unterstützung | Nicht unterstützt, nur per Entfernen umgehbar | Konfigurierbare Strategien verfügbar |
| Throttling | Feingranular über Lag und interaktiven Steuerkanal | Über Lag-Schwellenwert und Pause-Datei |
| Testbarkeit vor Produktiveinsatz | Dedizierter --test-on-replica-Modus | Nur Dry-Run ohne echten Replica-Test |
| Voraussetzung Binlog-Format | binlog_format=ROW zwingend | Keine besondere Anforderung |
Mironsoft
Datenbank-Performance, Index-Tuning und Magento-DB-Optimierung
Magento-Shop, der an langsamen Datenbankabfragen leidet?
Wir analysieren MySQL-Datenbanken auf Performance-Bremsen, optimieren Indizes und Abfragen gezielt und richten Backup- und Replikationsstrategien ein, die im Ernstfall wirklich funktionieren.
Performance-Audit
Slow Query Log und Explain-Pläne systematisch auf Engpässe untersuchen.
Index-Optimierung
Indizes gezielt für die tatsächliche Abfragelast des Shops aufbauen.
Backup-Strategie
Zuverlässige Backup- und Restore-Prozesse für produktive Magento-Datenbanken einrichten.
10. Zusammenfassung
gh-ost: Triggerlose Migrationen
Binlog statt Trigger
gh-ost verhält sich wie ein Replica und liest Änderungen asynchron aus dem Binärlog statt über synchrone Trigger.
Kein Schreib-Overhead
Die Originaltabelle bleibt beim Schreiben unbeeinflusst, ideal für sehr schreibintensive Magento-Tabellen.
Fremdschlüssel-Lücke
Fremdschlüssel werden nicht unterstützt, nur über --discard-foreign-keys vollständig umgehbar.
Sicherer Workflow
Test-Run auf Replica, Dry-Run, feingranulares Throttling und ein atomarer Cut-Over minimieren das Risiko.