Heeft u last gehad van trage MySQL-opstarttijden in GTID-modus? We kwamen onlangs dit probleem tegen bij een van onze MySQL-hostingimplementaties en wilden het probleem oplossen. In deze blog bespreken we het probleem dat de herstarttijd van MySQL kan vertragen, hoe u fouten kunt opsporen voor uw implementatie en wat u kunt doen om uw starttijd te verkorten en uw begrip van op GTID gebaseerde replicatie te verbeteren.
Hoe we het probleem hebben gevonden
We onderzochten trage MySQL-opstarttijden bij een low-end, schijfgebaseerde MySQL 5.7.21-implementatie waarvoor de GTID-modus was ingeschakeld. Het systeem maakte deel uit van een master-slave-paar en stond onder een matige schrijfbelasting. Bij het opnieuw opstarten tijdens gepland onderhoud merkten we dat de databaseserver 5-10 minuten nodig had om op te starten en verbindingen te accepteren. Dat soort vertraging was niet logisch, dus gingen we op onderzoek uit.
Debuggen van uw trage MySQL-starttijd
We gebruikten de populaire Percona-tool pt-ioprofile om te zien wat de database aan het doen was. pt-ioprofile is een zeer belangrijk hulpprogramma in de populaire toolkit van Percona dat wordt gebruikt om MySQL-problemen op te lossen, en u kunt de volledige lijst met functies bekijken in hun documentatie. Het pt-ioprofile tool gebruikt strace en lsof om de I/O van een proces te bekijken en een tabel met bestanden en I/O-activiteit af te drukken.
Dus we begonnen MySQL, wachtten op de mysqld proces om voortgebracht te worden, en startte pt-ioprofile om te zien wat het probleem kan zijn:
# 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 ...
Wat vertraagt het opnieuw opstarten van MySQL?
Bij het meerdere keren uitvoeren, hebben we het volgende opgemerkt:
- De mysqld proces besteedde het grootste deel van zijn tijd aan het lezen van het laatste binaire logbestand. Dit was zelfs het geval wanneer de server netjes was gestopt en er geen noodherstel was, enzovoort.
- De server besteedde ook een aanzienlijke hoeveelheid tijd aan het laden van de InnoDB-gegevensbestanden, maar die tijd was veel korter in vergelijking met de tijd die werd besteed aan het lezen van het nieuwste binaire logbestand.
- Als de server onmiddellijk opnieuw zou worden opgestart, zou deze volgende herstart veel sneller zijn.
- Aangezien het afsluiten van een database het binaire logboek leegt en een nieuw logboek maakt bij het opstarten, hebben we een aanvullend experiment gedaan - voordat we de server uitschakelden, hebben we de binaire logboeken leeggemaakt. De daaropvolgende serverstart was weer snel.
Deze observaties wezen er duidelijk op dat MySQL veel tijd besteedde aan het lezen van het nieuwste binaire logbestand. Als het bestand klein was, zoals het geval zou zijn wanneer het logbestand werd leeggemaakt voordat het werd afgesloten, was het opstarten snel.
Trage MySQL-starttijd in GTID? De grootte van uw binaire logbestand kan het probleem zijnKlik om te tweeten
Inzicht in Binlog GTID-herstel
Het blijkt dat, om de waarden van gtid_executed en gtid_purged te vullen, de MySQL-server de binaire logbestanden moet ontleden.
Hier is de samenvatting van de aanbeveling voor de MySQL 5.7-documentatiemethode op basis van een FALSE of TRUE-waarde:
Wanneer binlog_gtid_simple_recovery =ONWAAR:
Om gtid_executed te berekenen:
- Herhaal binaire logbestanden van de nieuwste, stop bij het eerste bestand met een Previous_gtids_log_event invoer.
- Gebruik alle GTID's van Previous_gtids_log_event en Gtid_log_events uit dit binaire logbestand en sla deze GTID-set intern op. Het wordt gtids_in_binlog genoemd.
- Waarde van gtid_executed wordt berekend als de unie van gtids_in_binlog en de GTID's in de mysql.gtid_executed tabel .
Dit proces kan erg tijdrovend zijn als er een groot aantal binaire logbestanden zonder GTID's is, bijvoorbeeld gemaakt wanneer gtid_mode =UIT.
Evenzo, om gtid_purged: te berekenen
- Herhaal binaire logbestanden van de oudste naar de nieuwste, stop bij het eerste binaire log dat ofwel een niet-lege Vorige_gtids_log_event bevat (heeft ten minste één GTID), of die ten minste één Gtid_log_event heeft .
- Lees Previous_gtids_log_event uit dit bestand. Bereken de interne variabele gtids_in_binlog_not_purged omdat deze GTID-set is afgetrokken van gtids_in_binlog.
- Waarde van gtid_purged is ingesteld op gtid_executed , minus gtids_in_binlog_not_purged .
Dit vormt dus de basis van ons begrip van hoe dingen vroeger werkten in oudere versies. Bepaalde optimalisaties kunnen echter worden gemaakt wanneer binlog_gtid_simple_recovery is waar. Dit is het geval waarin we geïnteresseerd zijn:
Wanneer binlog_gtid_simple_recovery =WAAR:
(Let op, dit is de standaardinstelling in MySQL 5.7.7 en hoger)
- Lees alleen de oudste en de nieuwste binaire logbestanden.
- Compute gtid_purged van het Previous_gtids_log_event of Gtid_log_event gevonden in het oudste binaire logbestand.
- Compute gtid_executed van het Previous_gtids_log_event of Gtid_log_event gevonden in nieuwste binaire logbestand.
- Dus slechts twee binaire logbestanden worden gelezen tijdens het opnieuw opstarten van de server of bij het opschonen van binaire logboeken.
Dus voor MySQL-versies 5.7.7 en hoger worden de nieuwste en oude binaire logbestanden altijd gelezen tijdens het opstarten van het systeem om GTID-systeemvariabelen correct te initialiseren. Het lezen van het oudste binaire logbestand is niet zo duur, aangezien de gebeurtenis waar MySQL naar zoekt, Previous_gtids_log_event, altijd de eerste gebeurtenis in een binair logbestand is.
Echter, om gtid_executed correct te berekenen , moet de server het volledige nieuwste binaire logbestand lezen en alle gebeurtenissen in dat bestand verzamelen. De opstarttijd van het systeem wordt dus recht evenredig met de grootte van het laatste binaire logbestand .
Merk op dat de situatie nog erger is wanneer binlog_gtid_simple_recovery is FALSE . Aangezien het niet langer de standaardoptie is in recente releases, is het geen probleem.
Hoe u uw trage starttijd kunt oplossen
Na de oorzaak van het probleem waar we tegenaan liepen te hebben begrepen, lag de oplossing die we besloten vrij voor de hand:de grootte van de binaire logbestanden verkleinen. De standaardgrootte van binaire logbestanden is 1 GB. Het kost tijd om een bestand van deze grootte te ontleden tijdens het opstarten, dus het is logisch om de waarde van max_binlog_size te verlagen naar een lagere waarde.
Als het verkleinen van het binaire logbestand geen optie is, kan het helpen om de binaire logbestanden leeg te maken net voordat het mysqld-proces voor onderhoud wordt afgesloten. om de binlog GTID-hersteltijden te verkorten.