Hai riscontrato tempi di avvio di MySQL lenti in modalità GTID? Di recente abbiamo riscontrato questo problema su una delle nostre distribuzioni di hosting MySQL e abbiamo deciso di risolvere il problema. In questo blog, analizziamo il problema che potrebbe rallentare i tempi di riavvio di MySQL, come eseguire il debug per la tua distribuzione e cosa puoi fare per ridurre il tempo di inizio e migliorare la tua comprensione della replica basata su GTID.
Come abbiamo riscontrato il problema
Stavamo studiando i tempi di avvio lenti di MySQL su un'implementazione MySQL 5.7.21 basata su disco di fascia bassa con la modalità GTID abilitata. Il sistema faceva parte di una coppia master-slave ed era soggetto a un carico di scrittura moderato. Al riavvio durante una manutenzione programmata, abbiamo notato che il server del database impiegava 5-10 minuti per avviarsi e iniziare ad accettare le connessioni. Questo tipo di ritardo non aveva senso, quindi abbiamo deciso di indagare.
Debug dell'ora di inizio di MySQL lenta
Abbiamo usato il popolare strumento Percona pt-ioprofile per vedere cosa stava facendo il database. pt-ioprofilo è un'utilità molto importante nel popolare toolkit di Percona utilizzato per eseguire il debug dei problemi di MySQL e puoi vedere l'elenco completo delle funzionalità nella loro documentazione. Il pt-ioprofile lo strumento utilizza strace e lsof per guardare l'I/O di un processo e stampare una tabella di file e attività di I/O.
Quindi, abbiamo avviato MySQL, abbiamo aspettato mysqld processo per essere generato e avviato pt-ioprofile per vedere quale potrebbe essere il problema:
; 0.000000 0.000000 0.000000 0.000015 0.000040 0.000000 0.000021 0.000000 /mysql_data/binlogs/mysql-bin.000014 ...Cosa rallenta il riavvio di MySQL?
Durante l'esecuzione più volte, abbiamo osservato quanto segue:
- Il mysqld il processo trascorreva la maggior parte del tempo a leggere l'ultimo file di registro binario. Ciò accadeva anche quando il server era stato arrestato in modo regolare e non era necessario un ripristino in caso di arresto anomalo, ecc.
- Il server ha anche impiegato una notevole quantità di tempo per caricare i file di dati di InnoDB, ma quel tempo è stato molto inferiore rispetto al tempo impiegato per leggere l'ultimo file di log binario.
- Se il server venisse riavviato immediatamente, questo successivo riavvio sarebbe molto più veloce.
- Poiché l'arresto del database cancella il log binario e ne crea uno nuovo all'avvio, abbiamo fatto un ulteriore esperimento:prima di spegnere il server, abbiamo svuotato i log binari. Il successivo avvio del server è stato di nuovo veloce.
Queste osservazioni indicavano chiaramente il fatto che MySQL passava molto tempo a leggere l'ultimo file di log binario. Se il file era piccolo, come lo sarebbe stato quando il file di registro è stato scaricato prima di un arresto, l'avvio è stato veloce.
Orario di inizio MySQL lento in GTID? Il problema potrebbe essere la dimensione del file di registro binarioFai clic per twittare
Capire il recupero di Binlog GTID
A quanto pare, per popolare i valori di gtid_executed e gtid_purged, il server MySQL deve analizzare i file di log binari.
Ecco il riepilogo della raccomandazione del metodo di documentazione di MySQL 5.7 basata su una lettura FALSA o VERA:
Quando binlog_gtid_simple_recovery =FALSO:
Per calcolare gtid_executed:
- Esegui l'iterazione dei file di log binari dal più recente, fermandosi al primo file che ha un Previous_gtids_log_event voce.
- Consuma tutti i GTID da Previous_gtids_log_event e Gtid_log_events da questo file di registro binario e archiviare questo set GTID internamente. Viene chiamato gtids_in_binlog.
- Valore di gtid_executed è calcolato come l'unione di gtids_in_binlog e i GTID nella tabella mysql.gtid_executed .
Questo processo può richiedere molto tempo se esiste un numero elevato di file di log binari senza GTID, ad esempio, creati quando gtid_mode =OFF.
Allo stesso modo, per calcolare gtid_purged:
- Esegui l'iterazione dei file di registro binari dal più vecchio al più recente, fermandosi al primo registro binario che contiene un Previous_gtids_log_event non vuoto (ha almeno un GTID) o che ha almeno un Gtid_log_event .
- Leggi Previous_gtids_log_event da questo file. Calcola la variabile interna gtids_in_binlog_not_purged poiché questo set di GTID è stato sottratto da gtids_in_binlog.
- Valore di gtid_purged è impostato su gtid_executed , meno gtids_in_binlog_not_purged .
Quindi, questo costituisce la base della nostra comprensione di come funzionavano le cose nelle versioni precedenti. Tuttavia, alcune ottimizzazioni possono essere effettuate quando binlog_gtid_simple_recovery è vero. Questo è il caso che ci interessa:
Quando binlog_gtid_simple_recovery =VERO:
(Nota, questa è l'impostazione predefinita in MySQL 5.7.7 e versioni successive)
- Leggi solo i file di log binari più vecchi e più recenti.
- Calcola gtid_purged dal Previous_gtids_log_event o Gtid_log_event trovato nel file di registro binario più vecchio.
- Calcola gtid_executed dal Previous_gtids_log_event o Gtid_log_event trovato nel file di registro binario più recente.
- Quindi, solo due file di log binari vengono letti durante il riavvio del server o durante l'eliminazione dei log binari.
Quindi, per le versioni MySQL 5.7.7 e successive, i file di log binari più recenti e precedenti vengono sempre letti durante l'avvio del sistema per inizializzare correttamente le variabili di sistema GTID. Leggere il file di registro binario più vecchio non è così costoso poiché l'evento che MySQL sta cercando, Previous_gtids_log_event, è sempre il primo evento in un file di registro binario.
Tuttavia, per calcolare correttamente gtid_executed , il server deve leggere l'intero file di registro binario più recente e raccogliere tutti gli eventi in quel file. Quindi, il tempo di avvio del sistema diventa direttamente proporzionale alla dimensione dell'ultimo file di registro binario .
Nota che la situazione è ancora peggiore quando binlog_gtid_simple_recovery è FALSO . Dal momento che non è più l'opzione predefinita nelle versioni recenti, non è molto preoccupante.
Come risolvere il tuo tempo di inizio lento
Avendo compreso la causa del problema che stavamo riscontrando, la soluzione che abbiamo deciso era abbastanza ovvia:ridurre le dimensioni dei file di registro binari. La dimensione predefinita dei file di registro binari è 1 GB. Ci vuole tempo per analizzare un file di queste dimensioni durante l'avvio, quindi ha senso diminuire il valore di max_binlog_size a un valore inferiore.
Se la riduzione della dimensione del file di registro binario non è un'opzione, può essere utile svuotare i file di registro binari appena prima di un arresto per manutenzione del processo mysqld per diminuire i tempi di recupero del GTID binlog.