Har du oplevet langsomme MySQL-starttider i GTID-tilstand? Vi stødte for nylig på dette problem på en af vores MySQL-hosting-implementeringer og satte os for at løse problemet. I denne blog opdeler vi det problem, der kan forsinke dine MySQL-genstarttider, hvordan du fejlretter til din implementering, og hvad du kan gøre for at reducere din starttid og forbedre din forståelse af GTID-baseret replikering.
Sådan fandt vi problemet
Vi undersøgte langsomme MySQL-starttider på en low-end, diskbaseret MySQL 5.7.21-implementering, som havde GTID-tilstand aktiveret. Systemet var en del af et master-slave-par og var under en moderat skrivebelastning. Ved genstart under en planlagt vedligeholdelse bemærkede vi, at databaseserveren tog 5-10 minutter at starte op og begynde at acceptere forbindelser. Den slags forsinkelse gav ikke mening, så vi satte os for at undersøge sagen.
Fejlretning af din langsomme MySQL-starttid
Vi brugte det populære Percona-værktøj pt-ioprofile til at se, hvad databasen lavede. pt-ioprofil er et meget vigtigt værktøj i Perconas populære værktøjssæt, der bruges til at fejlfinde MySQL-problemer, og du kan se den komplette liste over funktioner i deres dokumentation. pt-ioprofilen værktøj bruger strace og lsof at se en process I/O og udskrive en tabel over filer og I/O-aktivitet.
Så vi startede MySQL, ventede på mysqld proces for at blive spawned, og startede pt-ioprofile for at se, hvad problemet kan være:
# pt-ioprofile --profile-process mysqld --run-time 200 Tue Oct 9 15:42:24 UTC 2018 Tracing process ID 18677 total pread read pwrite write fsync fdatasync open close getdents lseek fcntl filename ... 216.550641 0.000000 216.550565 0.000000 0.000000 0.000000 0.000000 0.000015 0.000040 0.000000 0.000021 0.000000 /mysql_data/binlogs/mysql-bin.000014 ...
Hvad sænker din MySQL-genstart?
Da vi kørte dette flere gange, observerede vi følgende:
- mysqld processen brugte det meste af sin tid på at læse den seneste binære logfil. Dette var tilfældet, selv når serveren var blevet stoppet elegant, og der ikke var behov for en nedbrudsgendannelse osv.
- Serveren brugte også meget tid på at indlæse InnoDB-datafilerne, men den tid var meget mindre sammenlignet med den tid, der blev brugt på at læse den seneste binære logfil.
- Hvis serveren blev genstartet igen med det samme, ville denne efterfølgende genstart være meget hurtigere.
- Da en databaselukning tømmer den binære log og opretter en ny ved opstart, lavede vi et ekstra eksperiment – før vi lukkede serveren ned, tømmede vi de binære logfiler. Den efterfølgende serverstart var hurtig igen.
Disse observationer pegede tydeligt på det faktum, at MySQL brugte meget tid på at læse den seneste binære logfil. Hvis filen var lille, som den ville være, når logfilen blev tømt før en nedlukning, var opstarten hurtig.
Langsom MySQL-starttid i GTID? Din binære logfilstørrelse kan være problemet. Klik for at tweete
Forstå Binlog GTID-gendannelse
Som det viser sig, skal MySQL-serveren parse de binære logfiler for at udfylde værdierne for gtid_executed og gtid_purged.
Her er oversigten over MySQL 5.7-anbefalingen til dokumentationsmetode baseret på en FALSK eller SAND læsning:
Når binlog_gtid_simple_recovery =FALSK:
For at beregne gtid_executed:
- Gentag binære logfiler fra de nyeste, og stop ved den første fil, der har en Previous_gtids_log_event indgang.
- Forbrug alle GTID'er fra Previous_gtids_log_event og Gtid_log_events fra denne binære logfil, og gem dette GTID-sæt internt. Det omtales som gtids_in_binlog.
- Værdi af gtid_executed beregnes som foreningen af gtids_in_binlog og GTID'erne i mysql.gtid_executed-tabellen .
Denne proces kan være meget tidskrævende, hvis der er et stort antal binære logfiler uden GTID'er, f.eks. oprettet når gtid_mode =OFF.
Tilsvarende for at beregne gtid_purged:
- Gentag binære logfiler fra den ældste til den nyeste, og stop ved den første binære log, der enten indeholder en ikke-tom Previous_gtids_log_event (har mindst ét GTID), eller som har mindst én Gtid_log_event .
- Læs Previous_gtids_log_event fra denne fil. Beregn den interne variabel gtids_in_binlog_not_purged da dette GTID-sæt er trukket fra gtids_in_binlog.
- Værdi af gtid_purged er indstillet til gtid_executed , minus gtids_in_binlog_not_purged .
Så dette danner grundlaget for vores forståelse af, hvordan tingene plejede at fungere i ældre versioner. Visse optimeringer kan dog foretages, når binlog_gtid_simple_recovery er sandt. Dette er sagen, vi er interesserede i:
Når binlog_gtid_simple_recovery =SAND:
(Bemærk, dette er standard i MySQL 5.7.7 og nyere)
- Læs kun de ældste og de nyeste binære logfiler.
- Compute gtid_purged fra Previous_gtids_log_event eller Gtid_log_event fundet i den ældste binære logfil.
- Beregn gtid_executed fra Previous_gtids_log_event eller Gtid_log_event fundet i den nyeste binære logfil.
- Derfor er kun to binære logfiler læses under servergenstarten eller ved udrensning af binære logfiler.
Så for MySQL versioner 5.7.7 og nyere læses de seneste og gamle binære logfiler altid under systemstart for at initialisere GTID-systemvariablerne korrekt. Det er ikke så dyrt at læse den ældste binære logfil, da begivenheden MySQL leder efter, Previous_gtids_log_event, er altid den første begivenhed i en binær logfil.
Men for at kunne beregne gtid_executed korrekt , skal serveren læse hele den seneste binære logfil og samle alle hændelser i den fil. Så systemets starttid bliver direkte proportional med størrelsen af den seneste binære logfil .
Bemærk, at situationen er endnu værre, når binlog_gtid_simple_recovery er FALSK . Da det ikke længere er standardindstillingen i de seneste udgivelser, er det ikke meget bekymrende.
Sådan løser du din langsomme starttid
Efter at have forstået årsagen til det problem, vi løb ind i, var den løsning, vi besluttede os for, ret indlysende – reducer størrelsen af de binære logfiler. Standardstørrelsen på binære logfiler er 1 GB. Det tager tid at parse gennem en fil af denne størrelse under opstart, så det giver mening at reducere værdien af max_binlog_size til en lavere værdi.
Hvis det ikke er en mulighed at formindske størrelsen af den binære logfil, kan det hjælpe at tømme de binære logfiler lige før en vedligeholdelsesnedlukning af mysqld-processen for at reducere gendannelsestiderne for binlog GTID.