MySQL 8.0 medförde enorma förändringar och modifieringar som drevs av Oracle MySQL-teamet. Fysiska filer har ändrats. Till exempel, *.frm, *.TRG, *.TRN och *.par existerar inte längre. Massor av nya funktioner har lagts till såsom CTE (Common Table Expressions), Window Functions, Invisible Indexes, regexp (eller Regular Expression) - det senare har ändrats och ger nu fullt Unicode-stöd och är multibytesäker. Dataordboken har också ändrats. Den är nu inkorporerad med en transaktionsdatalexikon som lagrar information om databasobjekt. Till skillnad från tidigare versioner lagrades ordboksdata i metadatafiler och icke-transaktionella tabeller. Säkerheten har förbättrats med det nya tillägget av caching_sha2_password som nu är standardautentiseringen som ersätter mysql_native_password och erbjuder mer flexibilitet men skärpt säkerhet som måste använda antingen en säker anslutning eller en okrypterad anslutning som stöder lösenordsutbyte med ett RSA-nyckelpar.
Med alla dessa coola funktioner, förbättringar, förbättringar som MySQL 8.0 erbjuder, var vårt team intresserade av att avgöra hur väl den nuvarande versionen MySQL 8.0 presterar, särskilt med tanke på att vårt stöd för MySQL 8.0.x-versioner i ClusterControl är på väg (så håll utkik på den här). Det här blogginlägget kommer inte att diskutera funktionerna i MySQL 8.0, men har för avsikt att jämföra dess prestanda mot MySQL 5.7 och se hur det har förbättrats då.
Serverinställningar och miljö
För detta riktmärke tänker jag använda en minimal installation för produktion med följande AWS EC2-miljö:
Instanstyp:t2.xlarge instans
Lagring:gp2 (SSD-lagring med minst 100 och maximalt 16000 IOPS)
vCPUS:4
Minne:16GiB
MySQL 5.7 version:MySQL Community Server (GPL) 5.7.24
MySQL 8.0 version:MySQL Community Server - GPL 8.0.14
Det finns några anmärkningsvärda variabler som jag också har satt för detta riktmärke, som är:
- innodb_max_dirty_pages_pct =90 ## Detta är standardvärdet i MySQL 8.0. Se här för mer information.
- innodb_max_dirty_pages_pct_lwm=10 ## Detta är standardvärdet i MySQL 8.0
- innodb_flush_neighbors=0
- innodb_buffer_pool_instances=8
- innodb_buffer_pool_size=8GiB
Resten av variablerna som ställs in här för båda versionerna (MySQL 5.7 och MySQL 8.0) har redan ställts in av ClusterControl för dess my.cnf-mall.
Användaren jag använde här överensstämmer inte heller med den nya autentiseringen av MySQL 8.0 som använder caching_sha2_password. Båda serverversionerna använder istället mysql_native_password plus att variabeln innodb_dedicated_server är AV (standard), vilket är en ny funktion i MySQL 8.0.
För att göra livet enklare satte jag upp MySQL 5.7 Community-versionsnoden med ClusterControl från en separat värd och tog sedan bort noden i ett kluster och stängde av ClusterControl-värden för att göra MySQL 5.7-noden vilande (ingen övervakningstrafik). Tekniskt sett är båda noderna MySQL 5.7 och MySQL 8.0 vilande och inga aktiva anslutningar går genom noderna, så det är i grunden ett rent benchmarkingtest.
Använda kommandon och skript
För denna uppgift används sysbench för testning och lastsimulering för de två miljöerna. Här är följande kommandon eller skript som används i detta test:
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
Så skriptet förbereder helt enkelt sbtest-schemat och fyller i tabeller och poster. Sedan utför den läs/skrivladdningstester med skriptet /usr/share/sysbench/oltp_read_write.lua. Skriptet dumpar global status och MySQL-variabler, samlar in CPU-användning och analyserar InnoDB-radoperationer som hanteras av skriptet innodb-ops-parser.py. Skripten genererar sedan *.csv-filer baserat på de dumpade loggarna som samlades in under benchmark, sedan använde jag ett Excel-kalkylblad här för att generera grafen från *.csv-filer. Kontrollera koden här i detta github-förråd.
Låt oss nu fortsätta med grafresultaten!
InnoDB Row Operations
I princip här extraherade jag bara InnoDB-radoperationerna som väljer (läser), tar bort, infogar och uppdaterar. När antalet trådar går upp överträffar MySQL 8.0 betydligt MySQL 5.7! Båda versionerna har inga specifika konfigurationsändringar, utan bara de anmärkningsvärda variablerna jag har ställt in. Så båda versionerna använder i stort sett standardvärden.
Intressant nog, med avseende på påståendena från MySQL Server Team om prestanda för läsning och skrivning i den nya versionen, graferna pekar på en betydande prestandaförbättring, särskilt i en högbelastningsserver. Föreställ dig skillnaden mellan MySQL 5.7 och MySQL 8.0 för alla dess InnoDB-radoperationer, det är en stor skillnad, särskilt när antalet trådar går upp. MySQL 8.0 avslöjar att den kan fungera effektivt oavsett arbetsbelastning.
Transaktioner behandlade
Som visas i grafen ovan visar MySQL 8.0-prestanda återigen en enorm skillnad i den tid det tar att behandla transaktioner. Ju lägre, desto bättre presterar den, vilket betyder att det går snabbare att behandla transaktioner. De transaktioner som behandlas (den andra grafen) avslöjar också att båda antalet transaktioner inte skiljer sig från varandra. Det betyder att båda versionerna utför nästan samma antal transaktioner men skiljer sig i hur snabbt det kan slutföras. Även om jag skulle kunna säga, kan MySQL 5.7 fortfarande hantera mycket vid lägre belastning, men den realistiska belastningen, särskilt i produktionen, kan förväntas vara högre - särskilt den mest hektiska perioden.
Grafen ovan visar fortfarande transaktionerna som den kunde bearbeta men skiljer läsning från skrivning. Men det finns faktiskt extremvärden i graferna som jag inte inkluderade eftersom de är små godbitar av resultatet som skulle skeva grafen.
MySQL 8.0 avslöjar stora förbättringar speciellt för att göra läsningar. Den visar sin effektivitet i skrivningar speciellt för servrar med hög arbetsbelastning. Ett bra extra stöd som påverkar MySQL-prestandan för läsningar i version 8.0 är möjligheten att skapa ett index i fallande ordning (eller indexsökningar framåt). Tidigare versioner hade bara stigande eller bakåt indexsökning, och MySQL var tvungen att göra filsortering om den behövde en fallande ordning (om filsortering behövs kan du överväga att kontrollera värdet på max_längd_för_sort_data). Fallande index gör det också möjligt för optimeraren att använda index med flera kolumner när den mest effektiva skanningsordningen blandar stigande ordning för vissa kolumner och fallande ordning för andra. Se här för mer information.
CPU-resurser
Under denna benchmarking bestämde jag mig för att ta några hårdvaruresurser, framför allt CPU-användningen.
Låt mig först förklara hur jag tar CPU-resursen här under benchmarking. sysbench inkluderar inte samlad statistik för hårdvaruresurser som används eller används under processen när du benchmarkar en databas. På grund av det, vad jag gjorde var att skapa en flagga genom att skapa en fil, ansluta till målvärden via SSH och sedan skörda data från Linux-kommandot "top" och analysera det medan jag sov en sekund innan jag samlar in igen. Efter det, ta den mest enastående ökningen av CPU-användning för mysqld-processen och ta sedan bort flaggfilen. Du kan granska koden där jag har i github.
Så låt oss diskutera grafresultatet igen, det verkar avslöja att MySQL 8.0 förbrukar mycket CPU. Mer än MySQL 5.7. Det kan dock behöva hantera nya variabler som lagts till i MySQL 8.0. Till exempel kan dessa variabler påverka din 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
Variablerna med dess värden lämnas av standardvärdena för detta riktmärke. De tre första variablerna hanterar CPU för redo-loggning, vilket i MySQL 8.0 har varit en förbättring på grund av omdesign av hur InnoDB skriver till REDO-loggen. Variabeln innodb_log_spin_cpu_pct_hwm har CPU-affinitet, vilket betyder att den skulle ignorera andra CPU-kärnor om mysqld till exempel bara är fäst till 4 kärnor. För parallelllästa trådar, i MySQL 8.0, lägger den till en ny variabel för vilken du kan ställa in hur många trådar som ska användas.
Jag grävde dock inte vidare i ämnet. Det kan finnas sätt som prestanda kan förbättras genom att dra fördel av funktionerna som MySQL 8.0 har att erbjuda.
Slutsats
Det finns massor av förbättringar som finns i MySQL 8.0. Jämförelseresultaten avslöjar att det har skett en imponerande förbättring, inte bara när det gäller att hantera läsarbetsbelastningar, utan också på en hög läs-/skrivarbetsbelastning jämfört med MySQL 5.7.
Om vi går över till de nya funktionerna som MySQL 8.0 ser det ut att ha utnyttjat de mest uppdaterade teknologierna inte bara på programvara (som stora förbättringar för Memcached, Remote Management för bättre DevOps-arbete, etc.) men även i hårdvara. Ta till exempel ersättningen av latin1 med UTF8MB4 som standardteckenkodning. Detta skulle innebära att det skulle kräva mer diskutrymme eftersom UTF8 behöver 2-byte på icke-US-ASCII-tecken. Även om detta riktmärke inte utnyttjade den nya autentiseringsmetoden med caching_sha2_password, kommer det inte att påverka prestandan om den använder kryptering. När det väl har autentiserats lagras det i cache, vilket innebär att autentiseringen bara görs en gång. Så om du använder en användare för din klient kommer det inte att vara ett problem och är säkrare än de tidigare versionerna.
Eftersom MySQL utnyttjar den mest uppdaterade hårdvaran och mjukvaran, ändrar den sina standardvariabler. Du kan läsa här för mer information.
Sammantaget har MySQL 8.0 dominerat MySQL 5.7 effektivt.