Der Umgang mit großen Transaktionen war schon immer ein Schmerzpunkt im Galera Cluster. Die Art und Weise, wie die Writeset-Zertifizierung von Galera funktioniert, verursacht Probleme, wenn Transaktionen lang sind oder wenn eine einzelne Zeile häufig auf mehreren Knoten geändert wird. Infolgedessen müssen Transaktionen rückgängig gemacht und erneut versucht werden, was zu Leistungseinbußen führt. Glücklicherweise wurde dieses Problem in Galera 4, einer neuen Version von Galera von Codership, behoben. Diese Bibliothek wird in MariaDB 10.4 verwendet, daher ist die Installation von MariaDB 10.4 die einfachste Möglichkeit, die neu eingeführten Funktionen zu testen. In diesem Blog-Beitrag werden wir uns ansehen, wie die Streaming-Replikation verwendet werden kann, um Probleme zu entschärfen, die früher ein Standardproblem in früheren Galera-Versionen waren.
Wir werden drei Knoten der MariaDB Galera-Clusterversion 10.4.6 verwenden, die mit der Galera-Version 26.4.2 geliefert wird.
MariaDB [(none)]> show global status like 'wsrep_provider%';
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <[email protected]> |
| wsrep_provider_version | 26.4.2(r4498) |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.001 sec)
Es gibt drei Hauptprobleme, mit denen die Streaming-Replikation umgehen soll:
- Lange Transaktionen
- Große Transaktionen
- Hotspots in Tabellen
Betrachten wir sie einzeln und sehen wir, wie die Streaming-Replikation uns helfen kann, damit umzugehen, aber konzentrieren wir uns zuerst auf die Writeset-Zertifizierung – die Hauptursache für diese Probleme.
Writeset-Zertifizierung im Galera-Cluster
Der Galera-Cluster besteht aus mehreren beschreibbaren Knoten. Jede auf dem Galera-Cluster ausgeführte Transaktion bildet ein Writeset. Jeder Writeset muss zur Zertifizierung an alle Knoten im Cluster gesendet werden – ein Prozess, der sicherstellt, dass alle Knoten eine bestimmte Transaktion anwenden können. Writesets müssen auf allen Cluster-Knoten ausgeführt werden, sodass bei einem Konflikt die Transaktion nicht festgeschrieben werden kann. Was sind typische Gründe, warum die Transaktion nicht ausgeführt werden kann? Nun, die drei Punkte, die wir zuvor aufgelistet haben:
- Lange Transaktionen - länger dauert die Transaktion, wahrscheinlicher ist es, dass in der Zwischenzeit ein anderer Knoten Aktualisierungen ausführt, die schließlich mit dem Writeset in Konflikt geraten und ihn daran hindern, die Zertifizierung zu bestehen
- Große Transaktionen - Zunächst einmal sind große Transaktionen auch länger als kleine, wodurch das erste Problem ausgelöst wird. Das zweite Problem, das eng mit den großen Transaktionen zusammenhängt, ist das Volumen der Änderungen. Es werden mehr Zeilen aktualisiert, wahrscheinlicher ist, dass einige Schreibvorgänge auf einem anderen Knoten zu einem Konflikt führen und die gesamte Transaktion rückgängig gemacht werden müsste.
- Hotspots in Tabellen – es ist wahrscheinlicher, dass eine gegebene Zeile aktualisiert werden muss, wahrscheinlicher wird eine solche Aktualisierung gleichzeitig auf mehreren Knoten stattfinden, was dazu führt, dass einige der Transaktionen rückgängig gemacht werden müssen
Das Hauptproblem hierbei ist, dass Galera keine Sperre auf anderen Knoten als dem ursprünglichen Knoten einführt, auf dem die Transaktion geöffnet wurde. Der Zertifizierungsprozess basiert auf der Hoffnung, dass, wenn ein Knoten eine Transaktion ausführen könnte, andere dies auch können sollten. Es ist wahr, aber wie wir besprochen haben, gibt es Ausnahmefälle, in denen die Wahrscheinlichkeit, dass dies passiert, erheblich reduziert ist.
In Galera 4 hat sich das Verhalten mit Streaming-Replikation geändert und alle Sperren werden in allen Knoten übernommen. Transaktionen werden in Teile aufgeteilt und jeder Teil wird auf allen Knoten zertifiziert. Nach erfolgreicher Zertifizierung werden Zeilen auf allen Knoten im Cluster gesperrt. Es gibt ein paar Variablen, die bestimmen, wie genau das gemacht wird - wsrep_trx_fragment_size und wsrep_trx_fragment_unit definieren, wie groß das Fragment sein soll und wie es definiert werden soll. Es handelt sich um eine sehr feinkörnige Kontrolle:Sie können Fragmenteinheiten als Bytes, Anweisungen oder Zeilen definieren, was es ermöglicht, die Zertifizierung für jede in der Transaktion geänderte Zeile auszuführen. Werfen wir einen Blick darauf, wie Sie im wirklichen Leben von der Streaming-Replikation profitieren können.
Arbeiten mit der Streaming-Replikation
Betrachten wir das folgende Szenario. Wir müssen eine Transaktion ausführen, die mindestens 30 Sekunden dauert:
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Dann führen wir während der Ausführung SQL aus, das ähnliche Zeilen berührt. Dies wird auf einem anderen Knoten ausgeführt:
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Was wäre das Ergebnis?
Die erste Transaktion wird zurückgesetzt, sobald die zweite ausgeführt wird:
MariaDB [sbtest]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Query OK, 0 rows affected (0.001 sec)
Query OK, 667 rows affected (0.020 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.010 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.009 sec)
Rows matched: 667 Changed: 667 Warnings: 0
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
Query OK, 0 rows affected (0.001 sec)
Die Transaktion auf dem zweiten Knoten war erfolgreich:
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (0.002 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.004 sec)
Was wir tun können, um dies zu vermeiden, ist die Streaming-Replikation für die erste Transaktion zu verwenden. Wir werden Galera bitten, jede Zeilenänderung zu zertifizieren:
MariaDB [sbtest]> BEGIN; SET SESSION wsrep_trx_fragment_size=1 ; SET SESSION wsrep_trx_fragment_unit='rows' ; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT; SET SESSION wsrep_trx_fragment_size=0;
Query OK, 0 rows affected (0.001 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 667 rows affected (1.757 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.708 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.685 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Wie Sie sehen können, hat es dieses Mal gut funktioniert. Auf dem zweiten Knoten:
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (33.942 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.026 sec)
Interessant ist, dass Sie sehen können, dass die Ausführung des UPDATE fast 34 Sekunden dauerte - dies wurde durch die Tatsache verursacht, dass die anfängliche Transaktion durch die Streaming-Replikation alle geänderten Zeilen auf allen Knoten gesperrt hat und unsere zweite Transaktion warten musste die erste, die abgeschlossen wird, obwohl beide Transaktionen auf unterschiedlichen Knoten ausgeführt wurden.
Dies ist im Grunde genommen der Fall, wenn es um die Streaming-Replikation geht. Abhängig von den Anforderungen und dem Datenverkehr können Sie es weniger streng verwenden - wir haben jede Zeile zertifiziert, aber Sie können dies auf jede n-te Zeile oder jede Anweisung ändern. Sie können sogar über das zu zertifizierende Datenvolumen entscheiden. Dies sollte ausreichen, um die Anforderungen Ihrer Umgebung zu erfüllen.
Es gibt noch ein paar Dinge, an die wir Sie erinnern möchten. Zunächst einmal ist die Streaming-Replikation keineswegs eine Lösung, die standardmäßig verwendet werden sollte. Aus diesem Grund ist es standardmäßig deaktiviert. Der empfohlene Anwendungsfall besteht darin, manuell über Transaktionen zu entscheiden, die von der Streaming-Replikation profitieren würden, und sie auf Sitzungsebene zu aktivieren. Aus diesem Grund enden unsere Beispiele mit:
SET SESSION wsrep_trx_fragment_size=0;
Diese Anweisung (wsrep_trx_fragment_size auf 0 setzen) deaktiviert die Streaming-Replikation für die aktuelle Sitzung.
Eine andere Sache, an die Sie sich erinnern sollten – wenn Sie die Streaming-Replikation verwenden, wird sie die Tabelle „wsrep_streaming_log“ im Schema „mysql“ verwenden, um die Daten, die gestreamt werden, dauerhaft zu speichern. Anhand dieser Tabelle können Sie sich ein Bild von den Daten machen, die mithilfe der Streaming-Replikation über den Cluster übertragen werden.
Zum Schluss die Leistung. Dies ist auch einer der Gründe, warum Sie die Streaming-Replikation nicht ständig verwenden möchten. Der Hauptgrund dafür ist das Sperren - bei der Streaming-Replikation müssen Sie Zeilensperren auf allen Knoten erwerben. Dies braucht Zeit, um die Sperren zu erhalten, und falls Sie die Transaktion zurücksetzen müssen, wird es auch den Druck auf alle Knoten ausüben, das Zurücksetzen durchzuführen. Wir haben einen sehr schnellen Test der Auswirkungen auf die Leistung durchgeführt, die die Streaming-Replikation hat. Die Umgebung ist ausschließlich eine Testumgebung, also gehen Sie nicht davon aus, dass diese Ergebnisse auf der Produktionshardware gleich sind, es liegt eher an Ihnen, zu sehen, welche Auswirkungen dies haben könnte.
Wir haben vier Szenarien getestet:
- Baseline, global wsrep_trx_fragment_size=0 setzen;
- global festlegen wsrep_trx_fragment_unit='rows'; setze global wsrep_trx_fragment_size=1;
- global setzen wsrep_trx_fragment_unit='statements'; setze global wsrep_trx_fragment_size=1;
- global setzen wsrep_trx_fragment_unit='statements'; setze global wsrep_trx_fragment_size=5;
Wir haben Sysbench R/W-Test verwendet:
sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=4 --events=0 --time=300 --mysql-host=10.0.0.141 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=3306 --tables=32 --report-interval=1 --skip-trx=off --table-size=100000 --db-ps-mode=disable run
Die Ergebnisse sind:
- Transaktionen:82,91 pro Sek., Abfragen:1658,27 pro Sek. (100%)
- Transaktionen:54,72 pro Sek., Abfragen:1094,43 pro Sek. (66 %)
- Transaktionen:54,76 pro Sek., Abfragen:1095,18 pro Sek. (66 %)
- Transaktionen:70,93 pro Sek., Abfragen:1418,55 pro Sek. (86 %)
Wie Sie sehen können, sind die Auswirkungen erheblich, die Leistung sinkt sogar um 33 %.
Wir hoffen, dass Sie diesen Blogbeitrag informativ fanden und Ihnen einige Einblicke in die Streaming-Replikation gegeben haben, die mit Galera 4 und MariaDB 10.4 geliefert wird. Wir haben versucht, Anwendungsfälle und mögliche Nachteile dieser neuen Technologie abzudecken.