Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

Il progresso non si ferma, quindi i motivi per passare alle ultime versioni di MySQL stanno diventando sempre più convincenti. Non molto tempo fa, in uno dei nostri progetti, era giunto il momento di aggiornare gli accoglienti cluster Percona Server 5.7 alla versione 8. Tutto questo è successo sulla piattaforma Ubuntu Linux 16.04. Come eseguire tale operazione con tempi di inattività minimi e quali problemi abbiamo riscontrato durante l'aggiornamento: leggi in questo articolo.

Formazione

Qualsiasi aggiornamento del server del database è molto probabilmente associato alla riconfigurazione del database: modifiche ai requisiti per i limiti sulle risorse di sistema e correzione delle configurazioni del database che devono essere cancellate da direttive obsolete.

Prima dell'aggiornamento faremo sicuramente riferimento alla documentazione ufficiale:

E redigiamo un piano d'azione:

  1. Correggere i file di configurazione rimuovendo le direttive obsolete.
  2. Verifica la compatibilità con le utilità.
  3. Aggiorna i database slave installando il pacchetto percona-server-server.
  4. Aggiorna il master con lo stesso pacchetto.

Diamo un'occhiata a ogni punto del piano e vediamo cosa potrebbe andare storto.

IMPORTANTE! La procedura per aggiornare un cluster MySQL basato su Galera ha le sue sottigliezze che non sono descritte nell'articolo. Non dovresti usare questa istruzione in questo caso.

Parte 1: controllo delle configurazioni

MySQL è stato rimosso nella versione 8 query_cache. In realtà lo era dichiarato obsoleto indietro nella versione 5.7, ma ora completamente cancellato. Di conseguenza è necessario eliminare le direttive associate. E per memorizzare nella cache le richieste ora puoi utilizzare strumenti esterni, ad esempio ProxySQL.

Inoltre nella configurazione c'erano direttive obsolete about innodb_file_format. Se in MySQL 5.7 era possibile selezionare il formato InnoDB, l'ottava versione funziona già solo con formato Barracuda.

Il nostro risultato è la rimozione delle seguenti direttive:

  • query_cache_type, query_cache_limit и query_cache_size;
  • innodb_file_format и innodb_file_format_max.

Per verificare utilizzeremo l'immagine Docker di Percona Server. Inseriremo la configurazione del server nella directory mysql_config_teste accanto ad esso creeremo directory per dati e log. Esempio di test di configurazione del server Percona:

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run  --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/  -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

In conclusione: nei log di Docker o nella directory con i log, a seconda delle configurazioni, apparirà un file in cui verranno descritte le direttive problematiche.

Ecco cosa avevamo:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] The syntax 'expire-logs-days' is deprecated and will be removed in a future release. Please use binlog_expire_logs_seconds instead.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.

Pertanto, dovevamo ancora capire le codifiche e sostituire la direttiva obsoleta expire-logs-days.

Parte 2: Controllo delle installazioni funzionanti

La documentazione dell'aggiornamento contiene 2 utilità per verificare la compatibilità del database. Il loro utilizzo aiuta l'amministratore a verificare la compatibilità della struttura dati esistente.

Cominciamo con la classica utility mysqlcheck. Esegui semplicemente:

mysqlcheck -u root -p --all-databases --check-upgrade

Se non vengono rilevati problemi, l'utilità uscirà con il codice 0:

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

Inoltre, nelle versioni moderne di MySQL è disponibile un'utilità mysql-shell (nel caso di Percona questo è il pacchetto percona-mysql-shell). Sostituisce il classico client mysql e combina le funzioni di un client, un editor di codice SQL e strumenti di amministrazione MySQL. Per controllare il server prima dell'aggiornamento, è possibile eseguire i seguenti comandi attraverso di esso:

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=/etc/mysql/my.cnf

Ecco i commenti che abbiamo ricevuto:

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

In generale, niente di critico: solo avvertimenti sulle codifiche (vedi sotto). Risultato complessivo dell'esecuzione:

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

Abbiamo deciso che l'aggiornamento dovrebbe avvenire senza problemi.

Una nota sugli avvisi di cui sopra che indicano problemi con le codifiche. Il fatto è che UTF-8 in MySQL fino a poco tempo fa non era "vero" UTF-8, poiché memorizzava solo 3 byte invece di 4. In MySQL 8 questo è finalmente possibile ha deciso di sistemarlo: pseudonimo utf8 porterà presto alla codifica utf8mb4e le vecchie colonne nelle tabelle diventeranno utf8mb3. Ulteriore codifica utf8mb3 verrà rimosso, ma non in questa versione. Pertanto, abbiamo deciso di correggere le codifiche già sull'installazione DBMS in esecuzione, dopo averla aggiornata.

Parte 3: Aggiornamenti del server

Cosa potrebbe andare storto quando esiste un piano così intelligente?... Comprendendo perfettamente che le sfumature si verificano sempre, abbiamo condotto il primo esperimento su un cluster di sviluppo MySQL.

Come già detto, documentazione ufficiale copre la questione dell'aggiornamento dei server MySQL con repliche. La conclusione è che dovresti prima aggiornare tutte le repliche (slave), poiché MySQL 8 può replicarsi da una versione master 5.7. Qualche difficoltà sta nel fatto che utilizziamo la modalità maestro <-> maestro, quando il master remoto è in modalità sola lettura. Cioè, in effetti, il traffico di combattimento va a un data center e il secondo è di backup.

La topologia è simile alla seguente:

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

L'aggiornamento deve iniziare con le repliche replica mysql dc 2, mysql master dc2 и mysql replica dc 1e terminiamo con il server mysql master dc 1. Per essere più affidabili, abbiamo arrestato le macchine virtuali, ne abbiamo scattato delle istantanee e immediatamente prima dell'aggiornamento abbiamo interrotto la replica con il comando STOP SLAVE. Il resto dell'aggiornamento è simile al seguente:

  1. Riavviamo ogni replica aggiungendo 3 opzioni alle configurazioni: skip-networking, skip-slave-start, skip-log-bin. Il fatto è che l'aggiornamento del database genera log binari con aggiornamenti alle tabelle di sistema. Queste direttive garantiscono che non verranno apportate modifiche ai dati dell'applicazione nel database e che le informazioni sull'aggiornamento delle tabelle di sistema non verranno incluse nei log binari. Ciò eviterà problemi durante la ripresa della replica.
  2. Installazione del pacchetto percona-server-server. È importante notare che nella versione MySQL 8 no è necessario eseguire il comando mysqlupgrade dopo l'aggiornamento del server.
  3. Dopo un avvio riuscito, riavviamo nuovamente il server, senza i parametri aggiunti nel primo paragrafo.
  4. Ci assicuriamo che la replica funzioni correttamente: controlla SHOW SLAVE STATUS e verificare che le tabelle con i contatori nel database dell'applicazione vengano aggiornate.

Sembra tutto abbastanza semplice: l'aggiornamento dello sviluppatore ha avuto successo. Ok, puoi tranquillamente programmare un aggiornamento notturno per la produzione.

Non c'era tristezza: abbiamo aggiornato il prodotto

Tuttavia, il trasferimento dell’esperienza di sviluppo di successo alla produzione non è stato privo di sorprese.

Fortunatamente, il processo di aggiornamento stesso inizia con le repliche, quindi quando abbiamo riscontrato difficoltà, abbiamo interrotto il lavoro e ripristinato la replica dallo snapshot. L'indagine sui problemi è stata rinviata al mattino successivo. I registri contenevano le seguenti voci:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] table: t1 has 19 columns but InnoDB dictionary has 20 columns
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Error in fixing SE data for db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Failed to Populate DD tables.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Aborting

La ricerca negli archivi di varie mailing list su Google ha portato alla comprensione che questo problema si verifica a causa di Bug di MySQL. Anche se questo è più probabilmente un bug di utilità mysqlcheck и mysqlsh.

Si scopre che MySQL ha cambiato il modo in cui rappresentano i dati per i campi decimali (int, tinyint, ecc.), quindi mysql-server utilizza un modo diverso per memorizzarli. Se il tuo database inizialmente era nella versione 5.5 o 5.1 e poi hai aggiornato alla 5.7, potresti dover fare OPTIMIZE per alcuni tavoli. Quindi MySQL aggiornerà i file di dati, trasferendoli nel formato di archiviazione corrente.

Puoi anche verificarlo con l'utility mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # формат поля
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

se field_type Se lo hai uguale a 0, nella tabella viene utilizzato il vecchio tipo: devi eseguirlo OPTIMIZE. Tuttavia, se il valore è 246, hai già un nuovo tipo. Maggiori informazioni sui tipi possono essere trovate in codice.

Inoltre, in questo bug Stiamo considerando la seconda possibile ragione, che ci ha ignorato: l'assenza di tabelle InnoDB nella tabella di sistema INNODB_SYS_TABLESPACES, se queste tabelle sono state create nella versione 5.1. Per evitare problemi durante l'aggiornamento, è possibile utilizzare script SQL allegato.

Perché non abbiamo avuto questi problemi in fase di sviluppo? Il database viene periodicamente copiato lì dalla produzione, quindi le tabelle vengono ricreate.

Sfortunatamente, su un database di grandi dimensioni davvero funzionante, non sarai in grado di prendere ed eseguire semplicemente un file universal OPTIMIZE. percona-toolkit ti aiuterà qui: l'utilità pt-online-schema-change è eccellente per l'operazione OPTIMIZE online.

Il piano aggiornato era simile al seguente:

  1. Ottimizza tutte le tabelle.
  2. Aggiornare i database.

Per verificarlo e allo stesso tempo scoprire l'ora dell'aggiornamento, abbiamo disabilitato una delle repliche ed eseguito il seguente comando per tutte le tabelle:

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

Le tabelle vengono aggiornate senza lunghi blocchi perché l'utilità crea una nuova tabella temporanea in cui copia i dati dalla tabella principale. Nel momento in cui entrambe le tabelle sono identiche, la tabella originale viene bloccata e sostituita con quella nuova. Nel nostro caso, un test ha dimostrato che ci vorrebbe circa un giorno per aggiornare tutte le tabelle, ma la copia dei dati causava un carico eccessivo sui dischi.

Per evitare ciò, in produzione abbiamo aggiunto l'argomento al comando --sleep con un valore di 10: questo parametro regola la durata di attesa dopo il trasferimento di un batch di dati in una nuova tabella. In questo modo è possibile ridurre il carico se l'effettiva applicazione in esecuzione richiede tempi di risposta.

Dopo aver eseguito l'ottimizzazione, l'aggiornamento ha avuto esito positivo.

...ma non del tutto!

Entro mezz'ora dall'aggiornamento, il client ha riscontrato un problema. Il database funzionava in modo molto strano: periodicamente si avviavano la connessione si ripristina. Questo è quello che si presentava nel monitoraggio:

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

Lo screenshot mostra un grafico a dente di sega dovuto al fatto che alcuni thread del server MySQL si bloccano periodicamente con un errore. Sono comparsi errori nell'applicazione:

[PDOException] SQLSTATE[HY000] [2002] Connection refused

Una rapida ispezione dei log ha rivelato che il demone mysqld non riusciva a ottenere le risorse richieste dal sistema operativo. Durante la risoluzione degli errori, abbiamo scoperto nel sistema File di policy di Apparmor "orfani".:

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

Questi file sono stati creati durante l'aggiornamento a MySQL 5.7 un paio di anni fa e appartengono a un pacchetto rimosso. L'eliminazione dei file e il riavvio del servizio Apparmor hanno risolto il problema:

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

insomma

Qualsiasi operazione, anche la più semplice, può portare a problemi imprevisti. E anche avere un piano ben congegnato non sempre garantisce il risultato atteso. Ora, tutti i piani di aggiornamento del nostro team includono anche la pulizia obbligatoria dei file non necessari che potrebbero essere comparsi come risultato di azioni recenti.

E con questa creatività grafica poco professionale vorrei dire un enorme grazie a Percona per i suoi ottimi prodotti!

Aggiornamento MySQL (Percona Server) da 5.7 a 8.0

PS

Leggi anche sul nostro blog:

Fonte: habr.com

Aggiungi un commento