MySQL 8.0 Tuning

Sul tuning di MySQL sono state pubbicate innumerevoli pagine nel web... ma MySQL ha avuto una continua evoluzione con nuovi algoritmi, nuovi parametri di tuning e variazioni sulle impostazioni di default. Con la versione 8.0 le variazioni sono notevoli sia rispetto alle versioni precedenti che rispetto ai fork quindi la maggior parte delle pagine sul tuning di MySQL o di esempi di configurazioni di my.cnf nel web non sono aggiornate ed affidabili!
Ecco perche' ho deciso di rimediare pubblicando questa pagina aggiornata a MySQL 8.0.

Questa semplice e pragmatica paginetta riporta quelli che sono i principali parametri di tuning di MySQL in versione 8.0 evitando di riportare i parametri non piu' significativi poiche' obsoleti.

Nel seguito sono riportate alcune informazioni di interesse organizzate in paragrafi specifici: Introduzione, Parametri principali, E se..., Varie ed eventuali.

Le indicazioni che seguono sono per un pubblico DBA adulto, per i minori o junior consigliamo la lettura di questo documento introduttivo, mentre le novita' della versione 8.0 sono riassunte in questo documento.

Introduzione

Il tuning di una base dati e' un'attivita' che richiede competenza ed esperienza. Se non sapete a cosa serve un parametro... non modificatelo!

Il tuning si fa se... serve. Se una base dati e' di modeste dimensioni, le applicazioni consolidate ed i sistemi correttamente dimensionati e' sufficiente un'impostazione iniziale ragionevole dei parametri e niente piu'.

Nessun tuning si sostituisce ad un disegno corretto della base dati e dell'SQL. Prima di qualsiasi altra attivita' vanno controllati evenuali statement di lunga durata e corretti quelli errati, vanno creati tutti gli indici necessari e, nei casi in cui opportuno, va utilizzato il partitioning e lo sharding.

Misurare, misurare, misurare! Misurare le prestazioni prima delle attivita' di tuning, misurare tutti i test eseguiti e continuare a misurare effettuata una modifica di parametri. Senza misure non si fa tuning. Quali misure? Tutte quelle che servono! In generale dipendono dall'applicazione e dall'utilizzo dei MySQL: TPS, MRT, #utenti, active threads, ... e dai sistemi ospite: %CPU, %IOW, LA, ... senza dimenticare le due principali: lo spazio ed il tempo (che come e' noto sono fisicamente legate tra loro :).

Parametri principali

Ecco l'elenco dei parametri in ordine di importanza! Naturalmente secondo il mio fallace personale giudizio...

E se...

Come cambiare la configurazione per ottimizzare le prestazioni se si utilizza...

Varie ed eventuali

Manca qualcosa? No: abbiamo descritto tutti i parametri utili!

In generale le configurazioni di default presenti nella 8.0 per tutti gli altri parametri sono gia' ottimali...
table_open_cache: era un parametro molto importante per il tuning ma il default e' passato a 2000 dalla 5.6 che e' un valore generalmente sufficiente se non sono ospitati troppi database su uno stesso server; table_open_cache_instances: riduce le contese sui latch delle tabelle ma in 8.0 il default e' 16, adatto per sfruttare anche i piu' recenti processori multi-core; innodb_file_per_table: e' assolutamente conveniente abilitarlo, ma e' gia' cosi' per default; innodb_data_file_path: consente di specificare i file e la dimensione di cui e' composta la partizione InnoDB; era importante quando si aveva il limite dei 2GB sui file e non si poteva utilizzare innodb_file_per_table, ora non si ha la necessita' di utilizzarlo; log_bin: e' giustamente disabilitato (rallenta) per default, e' pero' necessario per la replica o il PITR, quindi se serve si abilita altrimenti lo si lascia disabilitato: e' inutile riportalo come parametro di tuning; binlog_format: tranne in rari casi l'impostazione piu' efficiente e' quella ROW che e' gia' il default nella 8.0, le alternative sono STATEMENT (utile per le prestazioni in qualche specifico caso) e MIXED; tmp_table_size e max_heap_table_size: vanno aumentati rispetto al default (16M) solo se il rapporto CREATED_TMP_DISK_TABLES / CREATED_TMP_TABLES e' elevato e comunque dopo aver corretto eventuali query mal scritte; sync_relay_log: ha un forte impatto prestazionale sullo slave se viene impostato =1 ma il default e' 10000; innodb_flush_method: non cambiatelo! la scelta del metodo di flush puo' essere importante per le prestazioni in alcuni casi ma per valutare se cambiare rispetto al default fsync (eg. impostandolo a O_DIRECT che evita il double buffering) e' opportuno un benchmark specifico sui dischi ed una conoscenza esatta del comportamento dello storage e del sistema operativo, alcune impostazioni sono corrette su versioni e file system specifici (eg. O_DIRECT_NO_FSYNC 8.0.25+)... insomma io non lo cambio o ne sapete piu' di me o non cambiatelo; innodb_buffer_pool_instances: indica il numero di regioni in cui il buffer pool e' diviso per ridurre le contese dei latch. E' un'ottimizzazione significativa... ma il valore di default e' gia' adatto alla maggioranza dei casi; innodb_deadlock_detect: e' un nuovo parametro di tuning disponibile nella 8.0. Di default e' ad ON ed e' consigliato nella maggior parte dei casi. Su un benchmark si puo' disattivare ma non e' tipicamente il caso su un sistema di produzione perche' piu' efficace del classico timeout; innodb_doublewrite: non cambiatelo! a meno che non stiate eseguendo un benchmark non e' il caso di rischiare la corruzione del DB; ALTER INSTANCE DISABLE INNODB REDO_LOG: non eseguitelo! e' utile solo per un caricamento iniziale, se si ha un errore il DB va creato da zero; performance_schema: e' vero che ha un peso per le prestazioni, ma non e' consigliabile impostarlo ad OFF su un ambiente di produzione a meno che non siate certi della buona qualita' dell'SQL di tutte le applicazioni ospitate [NdA non sono tutti di questa opinione: su MariaDB per default e' disabilitato e lo stesso avviene con MySQL su Amazon RDS; al contrario Percona, benchmark alla mano, lo ritiene poco invasivo]; innodb_lru_scan_depth: il default (1024) va benissimo anche se ammetto di averlo abbassato a 256 in un paio di casi in caso di forti scritture, collegati a questo parametro sono il innodb_io_capacity, che viene trattato in modo diverso dalla 8.0.19 evitando picchi di I/O, innodb_io_capacity_max, innodb_page_cleaners, ... ; spesso sono presenti attese su lock che attendono fino a innodb_lock_wait_timeout, anche se e' possibile monitorarle con INNODB_ROW_LOCK_TIME, INNODB_ROW_LOCK_WAITS, INNODB_ROW_LOCK_CURRENT_WAITS, ... tipicamente non si puo' fare molto dal punto di vista del tuning ma solo agire sull'applicazione; max_allowed_packet: e' un parametro che spesso si modifica, ma non e' un parametro prestazionale; vm.swappiness: da impostare sempre a 1 su un DB server, ma e' un parametro del sistema operativo! ...


Manca qualcosa? Sicuramente si!

Sarebbe un grave errore pensare di poter riassumere tutto in una paginetta. I parametri MySQL della versione 8.0 sono centinaia e sono tutti importanti per sfruttare le funzionalita' ed ottenere le massime performance con MySQL.


Titolo: MySQL 8.0 Tuning
Livello: Esperto (4/5)
Data: 14 Febbraio 2019 ❤️ San Valentino
Versione: 1.0.1 - 14 Febbraio 2020 ❤️ San Valentino
Autore: mail [AT] meo.bogliolo.name