Analyse des Prinzips des MySQL-Extraktionsmodus für große Tabellen aus der Perspektive des Cloud-Datenmigrationsdienstes

Analyse des Prinzips des MySQL-Extraktionsmodus für große Tabellen aus der Perspektive des Cloud-Datenmigrationsdienstes

Zusammenfassung: Welche Methode sollte für die MySQL JDBC-Extraktion verwendet werden? Ich erkläre es Ihnen.

Ich wurde kürzlich bei einem Migrationsprojekt in der Cloud vom MySQL-Extraktionsmodus gequält. Zunächst wurden wir von Kunden wegen Speicherüberlaufs kritisiert, und dann erneut wegen der geringen Migrationseffizienz. Welche Methode sollte für die MySQL JDBC-Extraktion verwendet werden? Ich erkläre es Ihnen.

1.1 Java-JDBC-Kommunikationsprinzipien

Die Kommunikation zwischen JDBC und der Datenbank erfolgt über Socket. Der allgemeine Vorgang ist in der folgenden Abbildung dargestellt. Mysql-Server -> Kernel Socket Buffer -> Client Socket Buffer -> JVM, wo sich JDBC befindet

1.2 Drei Modi zum Lesen von JDBC-Daten

1.2.1 Methode 1: Daten mit JDBC-Standardparametern lesen

Es gliedert sich im Wesentlichen in folgende Schritte:

1) Der MySQL-Server schreibt Daten über OuputStream in den lokalen Kernelpuffer des Socket-Servers. Dies ist eine Speicherkopie.

2) Wenn sich Daten im lokalen Kennel-Puffer des Socket-Servers befinden, werden die Daten über die TCP-Verbindung in den Kennel-Puffer des Computers übertragen, auf dem sich der Socket-Client befindet.

3) Die JVM, in der sich JDBC befindet, verwendet InputSream, um lokale Kennel Buffer-Daten in den JVM-Speicher zu lesen. Wenn keine Daten vorhanden sind, wird das Lesen blockiert.

Der nächste Schritt besteht darin, den Vorgang 1, 2, 3 kontinuierlich zu wiederholen. Das Problem besteht darin, dass die JVM des Socket-Clients im Standardmodus den Kennel Buffer liest, ohne die Größe des lokalen Speichers zu berücksichtigen und so viel wie möglich liest. Wenn die Daten zu groß sind, führt dies zu einer FULL GC, gefolgt von einem Speicherüberlauf.

Siehe die JDBC-API-Dokumente. Der Java-Democode im Standardmodus lautet wie folgt

1.2.2 Methode 2: Cursorabfrage

Um das Speicherüberlaufproblem in Methode 1 zu lösen, stellt JDBC einen Cursorparameter bereit. Fügen Sie beim Herstellen einer JDBC-Verbindung useCursorFetch=true hinzu. Nach dem Setzen des Cursors teilt JDBC dem Server jedes Mal die zu extrahierende Datenmenge mit, um einen Speicherüberlauf zu vermeiden. Der Kommunikationsvorgang ist in der folgenden Abbildung dargestellt.

Obwohl die Cursorabfrage mit Methode 2 das Problem des Speicherüberlaufs löst, ist Methode 2 stark von der Netzwerkqualität abhängig. Wenn die Netzwerkverzögerung zunimmt und man davon ausgeht, dass jede Kommunikation um 10 ms zunimmt, dauern 100.000 Kommunikationen 1.000 Sekunden länger. Hier ist nur die RT jeder Anforderung. Jedes Mal, wenn TCP eine Nachricht sendet, erfordert es eine Rückmeldung ACK, um die Datenzuverlässigkeit sicherzustellen. Jedes Mal, wenn der Client 100 Zeilen abruft (die Anzahl der angeforderten Zeilen ist konfigurierbar), finden mehrere Kommunikationen statt, was das durch die erhöhte Latenz verursachte Effizienzproblem noch weiter verschärft. Darüber hinaus kann MySQL bei Cursorabfragen die Endverzögerung der Abfrage nicht vorhersagen. Um mit seinen eigenen DML-Operationen fertig zu werden, erstellt es lokal einen temporären Speicherplatz zum Speichern der zu extrahierenden Daten. Daher treten während der Cursorabfrage die folgenden Phänomene auf:

a. Die IOPS steigen sprunghaft an. Mysql schreibt während der Datenübertragung Daten in den temporären Speicher und liest Daten aus dem temporären Speicher, was eine große Anzahl von IO-Operationen auslöst.

b. Der Speicherplatz nimmt rapide zu. Der Lebenszyklus des temporären Speicherplatzes besteht während der gesamten JDBC-Lesephase und wird von MySQL erst dann zurückgefordert, wenn der Client Result.close() initiiert.

c. CPU und Speicher erhöhen sich um einen bestimmten Prozentsatz.

Informationen zu den Prinzipien der Cursorabfrage finden Sie im Blog „MySQL JDBC StreamResult Communication Principle Analysis and JDBC source code“, das in diesem Artikel nicht wiederholt wird.

In den JDBC-API-Dokumenten finden Sie den Java-Democode für den Cursormodus wie folgt

1.2.3 Methode 3: Daten aus dem Stream lesen

Methode 1 führt zu einem JVM-Speicherüberlauf. Obwohl Methode 2 keine vollständige GC verursacht, ist die Kommunikationseffizienz gering und führt außerdem dazu, dass die IOPS des Mysql-Servers in die Höhe schnellen und Speicherplatz verbrauchen. Daher führen wir Stream zum Lesen von Daten ein. Der Stream muss vor dem Lesen des Ergebnisses festgelegt werden

Bei Methode 3 wird vor der Kommunikation keine Server-Client-Interaktion durchgeführt, wodurch eine geringe Kommunikationseffizienz vermieden wird. Der Server bereitet Daten vor und schreibt sie in den Kennel-Puffer des Servers. Diese Daten werden über die TCP-Verbindung an den Kennel-Puffer des Clients übertragen. Anschließend wird die Methode inputStream.read() des Clients aktiviert, um die Daten zu lesen. Anders als bei Methode 1 liest der Client nur Daten in der Größe eines Pakets auf einmal. Wenn ein Paket nicht mit einer Zeile voll ist, wird ein weiteres Paket gelesen. Wenn der Client Daten langsamer verbraucht als die Datenübertragungsrate, sind die Daten im Zwingerbereich auf der Clientseite voll, und dann sind auch die Zwingerdaten auf der Serverseite voll, wodurch OuputStream blockiert wird. Auf diese Weise ist JDBC im Stream-Modus wie eine Wasserleitung, die zwei Reservoirs verbindet, und Client und Server erreichen ein Gleichgewicht.

Da für den JDBC-Client jedes Mal Daten aus dem Zwinger gelesen werden, ist die Effizienz viel höher als bei Methode 2 und das Lesen einer kleinen Datenmenge jedes Mal führt nicht zu einem Überlauf des JVM-Speichers. Für den Server schreibt Mysql jedes Mal Daten in den Zwinger. Es muss kein temporärer Speicherplatz erstellt werden, es sind keine E/A-Lesvorgänge erforderlich und auch der Druck auf den Server wird verringert. Natürlich bringt Methode 3 auch ihre eigenen Probleme mit sich, wie etwa die Unfähigkeit, beim Streaming abzubrechen, und die nicht blockierende Natur des Abbruchs.

Siehe die JDBC-API-Dokumente. Viele Online-Tutorials erfordern die Einstellung von useCursorFetch=trueResultSet.FETCH_REVERSE usw. Tatsächlich stellte der Editor nach dem Studium des JDBC-Treiberquellcodes fest, dass nur fetchSize=Integer.MIN_VALUE eingestellt werden muss und andere Konfigurationen mit der Standardkonfiguration übereinstimmen. Der Java-Democode für den Cursormodus lautet wie folgt

1.3 Optimierung des Cloud Data Migration Service in drei Modi

Cloud Data Migration (CDM) ist ein Migrationstool für Huawei Cloud. Weitere Einzelheiten finden Sie auf der offiziellen CDM-Website. Der Editor zeigt anhand von CDM, wie Sie zum Extrahieren von Daten zwischen drei Modi wechseln. CDM verwendet standardmäßig Modus 3, also die Streaming-Datenextraktion. Wenn Sie zu Modus 1 wechseln müssen, ist eine zusätzliche Konfiguration für Modus 2 erforderlich.

1.3.1 Konfigurationsmethode 1: Standardablesung

Erstellen Sie einen neuen Mysql-Connector. Einzelheiten zur Erstellung finden Sie auf der offiziellen Website. Fügen Sie in den erweiterten Eigenschaften useCursorFetch=false und adopt.stream=false hinzu.

1.3.2 Konfigurationsmethode 2: Cursorabfrage

Bearbeiten Sie den MySQL-Connector und fügen Sie in den erweiterten Eigenschaften useCursorFetch=true und adopt.stream=false hinzu. Die Größe der Cursorabfrage kann über die Abrufgröße auf der Schnittstelle angepasst werden, der Standardwert ist 1000.

1.3.3 Konfigurationsmethode 3: Streaming

CDM verwendet standardmäßig den Streaming-Modus und es ist keine zusätzliche Konfiguration erforderlich. Beachten Sie, dass im Stream-Modus Fetch Size auf der Schnittstelle ungültig ist. Informationen zum Grund finden Sie im vorherigen Abschnitt.

1.3.4 Leistungsvergleich

Erstellen Sie einen CDM-Migrationsjob für Mysql2Hive. Die Quelltabelle hat 101 Felder und 1 Million Datenzeilen. Die Konfiguration ist wie folgt:

Methode 1: Das Schreiben von 1 Million Datenzeilen dauert 1 Minute und 22 Sekunden.

Methode 2: Schreiben Sie auch 1 Million Zeilen, passen Sie fetchSzie jeweils auf 1, 10, 100, 100 an und der Mindestzeitaufwand beträgt 2m1s

Methode 3: Schreiben Sie auch 1 Million Zeilen und benötigen Sie 1m5s

Der Editor testete auch eine kleine Tabelle mit 1 Million Elementen. Es ist offensichtlich, dass die Geschwindigkeit von Methode 1 und Methode 3 viel höher ist als die von Methode 2. Darüber hinaus testete der Editor auch eine große Tabelle mit 10 Millionen Elementen. Methode 1 überschritt das Speicherlimit, Methode 2 migrierte normal, benötigte aber mehr als 20 Minuten, und Methode 3 konnte immer noch innerhalb von 15 Minuten abgeschlossen werden.

Damit ist dieser Artikel über die prinzipielle Analyse des MySQL-Extraktionsmodus für große Tabellen aus der Perspektive des Cloud-Datenmigrationsdienstes abgeschlossen. Weitere relevante Inhalte zur MySQL-Extraktion für große Tabellen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Implementierung der MySQL8.0.11-Datenverzeichnismigration
  • So migrieren Sie das Datenverzeichnis in mysql8.0.20
  • So migrieren Sie lokales MySQL in eine Serverdatenbank
  • Detaillierte Erläuterung von MySQL-Ereignisänderungsereignissen (ALTER EVENT), Deaktivierungsereignissen (DISABLE), Aktivierungsereignissen (ENABLE), Ereignisumbenennungen und Datenbankereignismigrationsvorgängen
  • Upgrade der Docker-Version von MySQL 5.7 auf MySQL 8.0.13, Datenmigration
  • Detaillierte Erklärung zur Migration einer MySQL-Datenbank auf einen anderen Computer
  • Die MySQL-Datenbankmigration exportiert und importiert schnell große Datenmengen
  • Python erstellt ein MySQL-Datenmigrationsskript
  • Zusammenfassung der MySQL-Datenmigration

<<:  Details zum JavaScript-Prototyp und zur Prototypkette

>>:  W3C Tutorial (2): W3C Programme

Artikel empfehlen

MySQL-Abfrage-Cache und Pufferpool

1. Caches - Abfrage-Cache Die folgende Abbildung ...

Detailliertes Verständnis des Lebenszyklusvergleichs zwischen Vue2 und Vue3

Inhaltsverzeichnis Zyklusvergleich Verwendung Zus...

Flex-Layout ermöglicht adaptive Seiten (Syntax und Beispiele)

Einführung in Flex Layout Flex bedeutet auf Engli...

Detaillierte Erläuterung der MySQL-Transaktionsverarbeitung

1. MySQL-Transaktionskonzept MySQL-Transaktionen ...

WeChat-Applet implementiert Suchfunktion und springt zur Suchergebnisseite

Suchseite: search.wxml-Seite: <view class=&quo...

js Promise-Methode zur gleichzeitigen Steuerung

Inhaltsverzeichnis Frage Hintergrund Idee & U...

Vue implementiert eine kleine Notizblockfunktion

In diesem Artikelbeispiel wird der spezifische Co...

Diskussion über sinnvollere Erstellungsregeln für MySQL-String-Indizes

Vorwort In Bezug auf die Verwendung von MySQL-Ind...

Detaillierte Erklärung der MySQL InnoDB-Indexerweiterung

Indexerweiterung: InnoDB erweitert automatisch je...

Mysql aktualisiert die Datenbank dynamisch - Skriptbeispiel - Erklärung

Das spezifische upgrade -Skript lautet wie folgt:...

So verwenden Sie SVG-Symbole in WeChat-Applets

SVG wurde in den letzten Jahren aufgrund seiner v...