MySQL 8.0 bracht enorme veranderingen en aanpassingen die werden doorgevoerd door het Oracle MySQL-team. Fysieke bestanden zijn gewijzigd. Bijvoorbeeld *.frm, *.TRG, *.TRN en *.par bestaan niet meer. Tal van nieuwe functies zijn toegevoegd, zoals CTE (Common Table Expressions), Window Functions, Invisible Indexes, regexp (of Regular Expression) - de laatste is gewijzigd en biedt nu volledige Unicode-ondersteuning en is multibyte veilig. Het datawoordenboek is ook veranderd. Het is nu opgenomen in een transactioneel datadictionary dat informatie over databaseobjecten opslaat. In tegenstelling tot eerdere versies werden woordenboekgegevens opgeslagen in metadatabestanden en niet-transactionele tabellen. De beveiliging is verbeterd met de nieuwe toevoeging van caching_sha2_password, wat nu de standaardverificatie is en mysql_native_password vervangt. Het biedt meer flexibiliteit, maar strengere beveiliging die een beveiligde verbinding of een niet-versleutelde verbinding moet gebruiken die wachtwoorduitwisseling met een RSA-sleutelpaar ondersteunt.
Met al deze coole functies, verbeteringen en verbeteringen die MySQL 8.0 biedt, was ons team geïnteresseerd om te bepalen hoe goed de huidige versie MySQL 8.0 presteert, vooral gezien het feit dat onze ondersteuning voor MySQL 8.0.x-versies in ClusterControl onderweg is (dus houd ons in de gaten op dit). Deze blogpost gaat niet in op de functies van MySQL 8.0, maar is bedoeld om de prestaties ervan te benchmarken met MySQL 5.7 en te kijken hoe het daarna is verbeterd.
Serverconfiguratie en -omgeving
Voor deze benchmark ben ik van plan een minimale installatie te gebruiken voor productie met behulp van de volgende AWS EC2-omgeving:
Instance-type:t2.xlarge instance
Opslag:gp2 (SSD-opslag met minimaal 100 en maximaal 16000 IOPS)
vCPUS:4
Geheugen:16GiB
MySQL 5.7-versie:MySQL Community Server (GPL) 5.7.24
MySQL 8.0 versie:MySQL Community Server - GPL 8.0.14
Er zijn ook enkele opvallende variabelen die ik voor deze benchmark heb ingesteld, namelijk:
- innodb_max_dirty_pages_pct =90 ## Dit is de standaardwaarde in MySQL 8.0. Zie hier voor details.
- innodb_max_dirty_pages_pct_lwm=10 ## Dit is de standaardwaarde in MySQL 8.0
- innodb_flush_neighbors=0
- innodb_buffer_pool_instances=8
- innodb_buffer_pool_size=8GiB
De rest van de variabelen die hier voor beide versies (MySQL 5.7 en MySQL 8.0) worden ingesteld, zijn al door ClusterControl aangepast voor zijn my.cnf-sjabloon.
Ook voldoet de gebruiker die ik hier heb gebruikt niet aan de nieuwe authenticatie van MySQL 8.0 die caching_sha2_password gebruikt. In plaats daarvan gebruiken beide serverversies mysql_native_password plus de variabele innodb_dedicated_server is UIT (standaard), wat een nieuwe functie is van MySQL 8.0.
Om het leven gemakkelijker te maken, heb ik het MySQL 5.7 Community-versieknooppunt met ClusterControl vanaf een afzonderlijke host ingesteld, vervolgens het knooppunt in een cluster verwijderd en de ClusterControl-host afgesloten om MySQL 5.7-knooppunt inactief te maken (geen controleverkeer). Technisch gezien zijn beide nodes MySQL 5.7 en MySQL 8.0 slapend en gaan er geen actieve verbindingen via de nodes, dus het is in wezen een pure benchmarking-test.
Gebruikte opdrachten en scripts
Voor deze taak wordt sysbench gebruikt voor het testen en laden van simulatie voor de twee omgevingen. Hier zijn de volgende commando's of scripts die bij deze test worden gebruikt:
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
Het script bereidt dus eenvoudig het sbtest-schema voor en vult tabellen en records. Vervolgens voert het lees-/schrijfbelastingstests uit met behulp van het /usr/share/sysbench/oltp_read_write.lua-script. Het script dumpt de globale status en MySQL-variabelen, verzamelt het CPU-gebruik en parseert InnoDB-rijbewerkingen die worden afgehandeld door het script innodb-ops-parser.py. De scripts genereren vervolgens *.csv-bestanden op basis van de gedumpte logbestanden die tijdens de benchmark zijn verzameld, daarna heb ik hier een Excel-spreadsheet gebruikt om de grafiek van *.csv-bestanden te genereren. Controleer de code hier in deze github-repository.
Laten we nu verder gaan met de grafiekresultaten!
InnoDB-rijbewerkingen
In principe heb ik hier alleen de InnoDB-rijbewerkingen geëxtraheerd die de selecties (lezingen), verwijderingen, invoegingen en updates uitvoeren. Wanneer het aantal threads stijgt, presteert MySQL 8.0 aanzienlijk beter dan MySQL 5.7! Beide versies hebben geen specifieke configuratiewijzigingen, maar alleen de opvallende variabelen die ik heb ingesteld. Beide versies gebruiken dus vrijwel standaardwaarden.
Interessant is dat met betrekking tot de beweringen van het MySQL Server Team over de prestaties van lezen en schrijven in de nieuwe versie, de grafieken wijzen op een aanzienlijke prestatieverbetering, vooral in een server met hoge belasting. Stel je het verschil voor tussen MySQL 5.7 en MySQL 8.0 voor al zijn InnoDB-rijbewerkingen, er is een groot verschil, vooral wanneer het aantal threads toeneemt. MySQL 8.0 laat zien dat het efficiënt kan presteren, ongeacht de werkdruk.
Transacties verwerkt
Zoals te zien is in de bovenstaande grafiek, laten de prestaties van MySQL 8.0 opnieuw een enorm verschil zien in de tijd die nodig is om transacties te verwerken. Hoe lager, hoe beter het presteert, wat betekent dat het sneller is om transacties te verwerken. Uit de verwerkte transacties (de tweede grafiek) blijkt ook dat beide aantallen transacties niet van elkaar verschillen. Dit betekent dat beide versies bijna hetzelfde aantal transacties uitvoeren, maar verschillen in hoe snel het kan worden voltooid. Hoewel ik zou kunnen zeggen, kan MySQL 5.7 nog steeds veel aan bij een lagere belasting, maar de realistische belasting, vooral in productie, zou naar verwachting hoger kunnen zijn - vooral de drukste periode.
De bovenstaande grafiek toont nog steeds de transacties die het kon verwerken, maar scheidt de lees- en schrijfbewerkingen. Er zijn echter uitschieters in de grafieken die ik niet heb opgenomen, omdat het kleine stukjes van het resultaat zijn die de grafiek scheef zouden trekken.
MySQL 8.0 onthult geweldige verbeteringen, vooral voor het lezen. Het toont zijn efficiëntie in schrijfbewerkingen, vooral voor servers met een hoge werkbelasting. Een geweldige toegevoegde ondersteuning die van invloed is op de MySQL-prestaties voor leesbewerkingen in versie 8.0, is de mogelijkheid om een index in aflopende volgorde te maken (of voorwaartse indexscans). Eerdere versies hadden alleen oplopende of achterwaartse indexscans en MySQL moest filesort uitvoeren als het een aflopende volgorde nodig had (als filesort nodig is, kunt u overwegen de waarde van max_length_for_sort_data te controleren). Aflopende indexen maken het voor het optimalisatieprogramma ook mogelijk om indexen met meerdere kolommen te gebruiken wanneer de meest efficiënte scanvolgorde een combinatie is van oplopende volgorde voor sommige kolommen en aflopende volgorde voor andere. Zie hier voor meer details.
CPU-bronnen
Tijdens deze benchmarking besloot ik wat hardwarebronnen te gebruiken, met name het CPU-gebruik.
Laat me eerst uitleggen hoe ik de CPU-bron hier neem tijdens benchmarking. sysbench bevat geen collectieve statistieken voor hardwarebronnen die worden gebruikt of gebruikt tijdens het proces wanneer u een database benchmarkt. Daarom heb ik een vlag gemaakt door een bestand te maken, verbinding te maken met de doelhost via SSH en vervolgens gegevens van het Linux-commando "top" te oogsten en het een seconde te ontleden terwijl ik sliep voordat ik het opnieuw verzamelde. Neem daarna de meest opvallende toename van het CPU-gebruik voor het mysqld-proces en verwijder vervolgens het vlagbestand. Je kunt de code daar bekijken die ik heb in github.
Dus laten we het opnieuw hebben over het grafiekresultaat, het lijkt te onthullen dat MySQL 8.0 veel CPU verbruikt. Meer dan MySQL 5.7. Het kan echter te maken hebben met nieuwe variabelen die zijn toegevoegd in MySQL 8.0. Deze variabelen kunnen bijvoorbeeld van invloed zijn op uw MySQL 8.0-server:
- 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
De variabelen met hun waarden worden gelaten door de standaardwaarden voor deze benchmark. De eerste drie variabelen verwerken de CPU voor het opnieuw loggen, wat in MySQL 8.0 een verbetering was vanwege het opnieuw ontwerpen van de manier waarop InnoDB naar het REDO-logboek schrijft. De variabele innodb_log_spin_cpu_pct_hwm heeft CPU-affiniteit, wat betekent dat het andere CPU-kernen zou negeren als mysqld bijvoorbeeld slechts aan 4 kernen is vastgemaakt. Voor parallelle leesthreads voegt het in MySQL 8.0 een nieuwe variabele toe waarvoor je kunt afstemmen hoeveel threads je wilt gebruiken.
Ik heb me echter niet verder verdiept in het onderwerp. Er kunnen manieren zijn waarop de prestaties kunnen worden verbeterd door gebruik te maken van de functies die MySQL 8.0 te bieden heeft.
Conclusie
Er zijn talloze verbeteringen die aanwezig zijn in MySQL 8.0. Uit de benchmarkresultaten blijkt dat er een indrukwekkende verbetering is opgetreden, niet alleen bij het beheer van de leesbelasting, maar ook bij de hoge lees-/schrijfbelasting in vergelijking met MySQL 5.7.
Als we naar de nieuwe functies van MySQL 8.0 gaan, lijkt het erop dat het gebruik heeft gemaakt van de meest up-to-date technologieën, niet alleen voor software (zoals een grote verbetering voor Memcached, Remote Management voor beter DevOps-werk, enz.) ook qua hardware. Neem bijvoorbeeld de vervanging van latin1 door UTF8MB4 als de standaardtekencodering. Dit zou betekenen dat er meer schijfruimte nodig zou zijn, aangezien UTF8 2 bytes nodig heeft op de niet-US-ASCII-tekens. Hoewel deze benchmark geen gebruik heeft gemaakt van de nieuwe authenticatiemethode met caching_sha2_password, heeft het geen invloed op de prestaties of er encryptie wordt gebruikt. Nadat het is geverifieerd, wordt het opgeslagen in de cache, wat betekent dat authenticatie slechts één keer wordt uitgevoerd. Dus als u één gebruiker voor uw klant gebruikt, is dat geen probleem en is het veiliger dan de vorige versies.
Omdat MySQL gebruikmaakt van de meest up-to-date hardware en software, verandert het de standaardvariabelen. U kunt hier lezen voor meer details.
Over het algemeen heeft MySQL 8.0 MySQL 5.7 efficiënt gedomineerd.