MySQL 8.0 brachte enorme Änderungen und Modifikationen mit sich, die vom Oracle MySQL Team vorangetrieben wurden. Physische Dateien wurden geändert. Beispielsweise existieren *.frm, *.TRG, *.TRN und *.par nicht mehr. Tonnenweise neue Funktionen wurden hinzugefügt, wie CTE (Common Table Expressions), Window Functions, Invisible Indexes, Regexp (oder Regular Expression) – letzteres wurde geändert und bietet nun volle Unicode-Unterstützung und ist Multibyte-sicher. Das Datenwörterbuch hat sich ebenfalls geändert. Es ist jetzt in ein Transaktionsdatenwörterbuch integriert, das Informationen zu Datenbankobjekten speichert. Im Gegensatz zu früheren Versionen wurden Wörterbuchdaten in Metadatendateien und nicht transaktionalen Tabellen gespeichert. Die Sicherheit wurde durch das neue Hinzufügen von caching_sha2_password verbessert, das jetzt die Standardauthentifizierung ist, die mysql_native_password ersetzt, und mehr Flexibilität, aber erhöhte Sicherheit bietet, die entweder eine sichere Verbindung oder eine unverschlüsselte Verbindung verwenden muss, die den Passwortaustausch mit einem RSA-Schlüsselpaar unterstützt.
Angesichts all dieser coolen Funktionen, Erweiterungen und Verbesserungen, die MySQL 8.0 bietet, war unser Team daran interessiert, die Leistung der aktuellen Version von MySQL 8.0 zu ermitteln, insbesondere angesichts der Tatsache, dass unsere Unterstützung für MySQL 8.0.x-Versionen in ClusterControl auf dem Weg ist (also bleiben Sie dran dazu). In diesem Blog-Beitrag werden nicht die Funktionen von MySQL 8.0 diskutiert, sondern beabsichtigt, seine Leistung mit MySQL 5.7 zu vergleichen und zu sehen, wie es sich seitdem verbessert hat.
Server-Setup und -Umgebung
Für diesen Benchmark beabsichtige ich, ein minimales Setup für die Produktion mit der folgenden AWS EC2-Umgebung zu verwenden:
Instanztyp:t2.xlarge-Instanz
Speicher:gp2 (SSD-Speicher mit mindestens 100 und maximal 16000 IOPS)
vCPUS:4
Speicher:16 GiB
MySQL 5.7-Version:MySQL Community Server (GPL) 5.7.24
MySQL 8.0-Version:MySQL Community Server - GPL 8.0.14
Es gibt einige bemerkenswerte Variablen, die ich auch für diesen Benchmark festgelegt habe, nämlich:
- innodb_max_dirty_pages_pct =90 ## Dies ist der Standardwert in MySQL 8.0. Einzelheiten finden Sie hier.
- innodb_max_dirty_pages_pct_lwm=10 ## Dies ist der Standardwert in MySQL 8.0
- innodb_flush_neighbors=0
- innodb_buffer_pool_instances=8
- innodb_buffer_pool_size=8GiB
Die restlichen Variablen, die hier für beide Versionen (MySQL 5.7 und MySQL 8.0) gesetzt werden, werden bereits von ClusterControl für seine my.cnf-Vorlage angepasst.
Außerdem entspricht der hier verwendete Benutzer nicht der neuen Authentifizierung von MySQL 8.0, die caching_sha2_password verwendet. Stattdessen verwenden beide Serverversionen mysql_native_password plus die innodb_dedicated_server-Variable ist AUS (Standard), was eine neue Funktion von MySQL 8.0 ist.
Um das Leben einfacher zu machen, habe ich den MySQL 5.7 Community-Versionsknoten mit ClusterControl von einem separaten Host eingerichtet, dann den Knoten in einem Cluster entfernt und den ClusterControl-Host heruntergefahren, um den MySQL 5.7-Knoten in den Ruhezustand zu versetzen (kein Überwachungsverkehr). Technisch gesehen sind beide Knoten MySQL 5.7 und MySQL 8.0 ruhend und es laufen keine aktiven Verbindungen durch die Knoten, also ist es im Wesentlichen ein reiner Benchmarking-Test.
Verwendete Befehle und Skripte
Für diese Aufgabe wird sysbench zum Testen und zur Lastsimulation für die beiden Umgebungen verwendet. Hier sind die folgenden Befehle oder Skripte, die bei diesem Test verwendet werden:
sb-prepare.sh
#!/bin/bash
host=$1
#host192.168.10.110
port=3306
user='sysbench'
password='[email protected]'
table_size=500000
rate=20
ps_mode='disable'
sysbench /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --threads=1 --max-requests=0 --time=3600 --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --tables=10 --report-interval=1 --skip-trx=on --table-size=$table_size --rate=$rate --db-ps-mode=$ps_mode prepare
sb-run.sh
#!/usr/bin/env bash
host=$1
port=3306
user="sysbench"
password="[email protected]"
table_size=100000
tables=10
rate=20
ps_mode='disable'
threads=1
events=0
time=5
trx=100
path=$PWD
counter=1
echo "thread,cpu" > ${host}-cpu.csv
for i in 16 32 64 128 256 512 1024 2048;
do
threads=$i
mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
tmpfile=$path/${host}-tmp${threads}
touch $tmpfile
/bin/bash cpu-checker.sh $tmpfile $host $threads &
/usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --events=$events --threads=$threads --time=$time --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --report-interval=1 --skip-trx=on --tables=$tables --table-size=$table_size --rate=$rate --delete_inserts=$trx --order_ranges=$trx --range_selects=on --range-size=$trx --simple_ranges=$trx --db-ps-mode=$ps_mode --mysql-ignore-errors=all run | tee -a $host-sysbench.log
echo "${i},"`cat ${tmpfile} | sort -nr | head -1` >> ${host}-cpu.csv
unlink ${tmpfile}
mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
done
python $path/innodb-ops-parser.py $host
mysql -h $host -e "SHOW GLOBAL VARIABLES" >> $host-global-vars.log
Das Skript bereitet also einfach das sbtest-Schema vor und füllt Tabellen und Datensätze. Dann führt es Lese-/Schreiblasttests mit dem Skript /usr/share/sysbench/oltp_read_write.lua durch. Das Skript gibt globale Status- und MySQL-Variablen aus, erfasst die CPU-Auslastung und analysiert InnoDB-Zeilenoperationen, die vom Skript innodb-ops-parser.py verarbeitet werden. Die Skripte generieren dann *.csv-Dateien basierend auf den ausgegebenen Protokollen, die während des Benchmarks gesammelt wurden, dann habe ich hier eine Excel-Tabelle verwendet, um das Diagramm aus *.csv-Dateien zu generieren. Bitte überprüfen Sie den Code hier in diesem Github-Repository.
Fahren wir nun mit den Diagrammergebnissen fort!
InnoDB-Zeilenoperationen
Im Grunde genommen habe ich hier nur die InnoDB-Zeilenoperationen extrahiert, die das Auswählen (Lesen), Löschen, Einfügen und Aktualisieren ausführen. Wenn die Anzahl der Threads steigt, übertrifft MySQL 8.0 MySQL 5.7 deutlich! Beide Versionen haben keine spezifischen Konfigurationsänderungen, sondern nur die bemerkenswerten Variablen, die ich gesetzt habe. Beide Versionen verwenden also ziemlich genau Standardwerte.
Interessanterweise weisen die Diagramme in Bezug auf die Behauptungen des MySQL Server-Teams über die Leistung von Lese- und Schreibvorgängen in der neuen Version auf eine signifikante Leistungsverbesserung hin, insbesondere bei einem Hochlastserver. Stellen Sie sich den Unterschied zwischen MySQL 5.7 und MySQL 8.0 für alle seine InnoDB-Zeilenoperationen vor, es gibt einen großen Unterschied, besonders wenn die Anzahl der Threads steigt. MySQL 8.0 zeigt, dass es unabhängig von seiner Arbeitslast effizient arbeiten kann.
Verarbeitete Transaktionen
Wie in der obigen Grafik gezeigt, zeigt die Leistung von MySQL 8.0 erneut einen großen Unterschied in der Zeit, die für die Verarbeitung von Transaktionen benötigt wird. Je niedriger, desto besser ist die Leistung, was bedeutet, dass Transaktionen schneller verarbeitet werden können. Auch die verarbeiteten Transaktionen (zweite Grafik) zeigen, dass sich die beiden Transaktionszahlen nicht voneinander unterscheiden. Das heißt, beide Versionen führen fast die gleiche Anzahl von Transaktionen aus, unterscheiden sich jedoch darin, wie schnell sie abgeschlossen werden können. Obwohl ich sagen könnte, dass MySQL 5.7 bei niedrigerer Last noch viel bewältigen kann, könnte die realistische Last, insbesondere in der Produktion, höher sein - insbesondere in der geschäftigsten Zeit.
Das obige Diagramm zeigt immer noch die Transaktionen, die verarbeitet werden konnten, trennt jedoch das Lesen von den Schreibvorgängen. Es gibt jedoch tatsächlich Ausreißer in den Diagrammen, die ich nicht aufgenommen habe, da es sich um winzige Leckerbissen des Ergebnisses handelt, die das Diagramm verzerren würden.
MySQL 8.0 zeigt große Verbesserungen, insbesondere für Lesevorgänge. Besonders bei Servern mit hoher Auslastung zeigt es seine Effizienz beim Schreiben. Eine großartige zusätzliche Unterstützung, die sich auf die MySQL-Leistung für Lesevorgänge in Version 8.0 auswirkt, ist die Möglichkeit, einen Index in absteigender Reihenfolge zu erstellen (oder Vorwärts-Index-Scans). Frühere Versionen hatten nur aufsteigende oder rückwärtsgerichtete Index-Scans, und MySQL musste filesortieren, wenn es eine absteigende Reihenfolge benötigte (wenn filesort benötigt wird, sollten Sie den Wert von max_length_for_sort_data überprüfen). Absteigende Indizes ermöglichen es dem Optimierer auch, mehrspaltige Indizes zu verwenden, wenn die effizienteste Scan-Reihenfolge eine aufsteigende Reihenfolge für einige Spalten und eine absteigende Reihenfolge für andere mischt. Weitere Einzelheiten finden Sie hier.
CPU-Ressourcen
Während dieses Benchmarkings habe ich mich entschieden, einige Hardware-Ressourcen zu nehmen, insbesondere die CPU-Auslastung.
Lassen Sie mich zunächst erklären, wie ich hier beim Benchmarking die CPU-Ressourcen nehme. sysbench enthält keine kollektiven Statistiken für Hardwareressourcen, die während des Prozesses verwendet oder verwendet werden, wenn Sie eine Datenbank bewerten. Aus diesem Grund habe ich ein Flag erstellt, indem ich eine Datei erstellt, eine Verbindung zum Zielhost über SSH hergestellt und dann Daten vom Linux-Befehl „top“ gesammelt und analysiert habe, während ich eine Sekunde lang schlafe, bevor ich sie erneut sammle. Nehmen Sie danach den herausragendsten Anstieg der CPU-Auslastung für den mysqld-Prozess und entfernen Sie dann die Flag-Datei. Sie können den Code dort überprüfen, den ich in github habe.
Lassen Sie uns also noch einmal über das Diagrammergebnis diskutieren, es scheint zu zeigen, dass MySQL 8.0 viel CPU verbraucht. Mehr als MySQL 5.7. Es muss jedoch möglicherweise mit neuen Variablen umgehen, die in MySQL 8.0 hinzugefügt wurden. Diese Variablen können sich beispielsweise auf Ihren MySQL 8.0-Server auswirken:
- innodb_log_spin_cpu_abs_lwm =80
- innodb_log_spin_cpu_pct_hwm =50
- innodb_log_wait_for_flush_spin_hwm =400
- innodb_parallel_read_threads =4
Die Variablen mit ihren Werten werden für diesen Benchmark auf ihren Standardwerten belassen. Die ersten drei Variablen verarbeiten die CPU für das Redo-Logging, was in MySQL 8.0 eine Verbesserung war, da InnoDB neu gestaltet hat, wie es in das REDO-Log schreibt. Die Variable innodb_log_spin_cpu_pct_hwm hat CPU-Affinität, was bedeutet, dass sie andere CPU-Kerne ignorieren würde, wenn mysqld beispielsweise nur an 4 Kerne gepinnt ist. Für parallele Lese-Threads fügt es in MySQL 8.0 eine neue Variable hinzu, für die Sie einstellen können, wie viele Threads verwendet werden sollen.
Allerdings habe ich mich nicht weiter mit dem Thema beschäftigt. Es gibt Möglichkeiten, die Leistung zu verbessern, indem Sie die Vorteile von MySQL 8.0 nutzen.
Schlussfolgerung
Es gibt unzählige Verbesserungen in MySQL 8.0. Die Benchmark-Ergebnisse zeigen, dass es eine beeindruckende Verbesserung gegeben hat, nicht nur bei der Verwaltung der Lese-Workloads, sondern auch bei einer hohen Lese-/Schreib-Workload im Vergleich zu MySQL 5.7.
Wenn wir zu den neuen Funktionen von MySQL 8.0 übergehen, sieht es so aus, als hätte es die aktuellsten Technologien nicht nur in Bezug auf Software (wie große Verbesserungen für Memcached, Remote Management für bessere DevOps-Arbeit usw.) genutzt, sondern auch auch in Hardware. Nehmen wir zum Beispiel das Ersetzen von latin1 durch UTF8MB4 als Standardzeichencodierung. Dies würde bedeuten, dass mehr Speicherplatz benötigt würde, da UTF8 2 Bytes für die Nicht-US-ASCII-Zeichen benötigt. Obwohl dieser Benchmark die Verwendung der neuen Authentifizierungsmethode mit caching_sha2_password nicht genutzt hat, wirkt sich dies nicht auf die Leistung aus, unabhängig davon, ob Verschlüsselung verwendet wird. Sobald es authentifiziert ist, wird es im Cache gespeichert, was bedeutet, dass die Authentifizierung nur einmal erfolgt. Wenn Sie also einen Benutzer für Ihren Client verwenden, stellt dies kein Problem dar und ist sicherer als die vorherigen Versionen.
Da MySQL die aktuellste Hardware und Software nutzt, ändert es seine Standardvariablen. Weitere Einzelheiten finden Sie hier.
Insgesamt hat MySQL 8.0 MySQL 5.7 effizient dominiert.