Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

Progresul nu stă pe loc, așa că motivele pentru a face upgrade la cele mai recente versiuni de MySQL devin din ce în ce mai convingătoare. Nu cu mult timp în urmă, într-unul dintre proiectele noastre, era timpul să actualizăm clusterele confortabile Percona Server 5.7 la versiunea 8. Toate acestea s-au întâmplat pe platforma Ubuntu Linux 16.04. Cum să efectuați o astfel de operațiune cu timp de nefuncționare minim și ce probleme am întâlnit în timpul actualizării - citiți în acest articol.

Pregătire

Orice actualizare a serverului bazei de date este cel mai probabil asociată cu reconfigurarea bazei de date: modificări ale cerințelor privind limitele resurselor de sistem și corectarea configurațiilor bazei de date care trebuie șters de directivele învechite.

Înainte de actualizare, ne vom referi cu siguranță la documentația oficială:

Și să întocmim un plan de acțiune:

  1. Corectați fișierele de configurare prin eliminarea directivelor învechite.
  2. Verificați compatibilitatea cu utilitățile.
  3. Actualizați bazele de date slave instalând pachetul percona-server-server.
  4. Actualizați masterul cu același pachet.

Să ne uităm la fiecare punct al planului și să vedem ce ar putea merge prost.

IMPORTANT! Procedura de actualizare a unui cluster MySQL bazat pe Galera are propriile sale subtilități care nu sunt descrise în articol. Nu ar trebui să utilizați această instrucțiune în acest caz.

Partea 1: Verificarea configurațiilor

MySQL a fost eliminat în versiunea 8 query_cache. De fapt, el era declarat invechit înapoi în versiunea 5.7, dar acum șterse complet. În consecință, este necesar să se elimine directivele asociate. Și pentru a stoca interogările în cache puteți utiliza acum instrumente externe - de exemplu, ProxySQL.

De asemenea, în config au existat directive învechite despre innodb_file_format. Dacă în MySQL 5.7 a fost posibil să se selecteze formatul InnoDB, atunci versiunea a 8-a funcționează deja doar cu format Barracuda.

Rezultatul nostru este eliminarea următoarelor directive:

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

Pentru a verifica, vom folosi imaginea Docker a Percona Server. Vom plasa configurația serverului în director mysql_config_test, iar alături vom crea directoare pentru date și jurnale. Exemplu de test de configurare Percona-server:

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

Concluzie: fie în jurnalele Docker, fie în directorul cu jurnalele - în funcție de configurațiile dvs. - va apărea un fișier în care vor fi descrise directivele problematice.

Iată ce am avut:

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.

Astfel, mai trebuia să ne dăm seama de codificări și să înlocuim directiva învechită expire-logs-days.

Partea 2: Verificarea instalațiilor de lucru

Documentația de actualizare conține 2 utilitare pentru verificarea compatibilității bazei de date. Utilizarea lor ajută administratorul să verifice compatibilitatea structurii de date existente.

Să începem cu utilitarul clasic mysqlcheck. Pur și simplu rulați:

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

Dacă nu sunt găsite probleme, utilitarul se va închide cu codul 0:

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

În plus, un utilitar este disponibil în versiunile moderne de MySQL mysql-shell (în cazul Percona acesta este pachetul percona-mysql-shell). Este un înlocuitor pentru clientul mysql clasic și combină funcțiile unui client, un editor de cod SQL și instrumente de administrare MySQL. Pentru a verifica serverul înainte de actualizare, puteți rula următoarele comenzi prin intermediul acestuia:

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

Iată comentariile pe care le-am primit:

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

În general, nimic critic - doar avertismente despre codificări (Vezi mai jos). Rezultatul general al executiei:

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

Am decis că actualizarea ar trebui să meargă fără probleme.

O notă despre avertismentele de mai sus indicând probleme cu codificări. Faptul este că UTF-8 în MySQL până de curând nu a fost „adevărat” UTF-8, deoarece a stocat doar 3 octeți în loc de 4. În MySQL 8, acesta este în sfârșit a decis să o repare: alias utf8 va duce în curând la codificare utf8mb4, iar coloanele vechi din tabele vor deveni utf8mb3. Codificare suplimentară utf8mb3 va fi eliminat, dar nu și în această versiune. Prin urmare, am decis să corectăm codificările deja pe instalația DBMS care rulează, după actualizarea acesteia.

Partea 3: Actualizări de server

Ce ar putea merge prost când există un astfel de plan inteligent?... Înțelegând bine că nuanțele apar întotdeauna, am efectuat primul experiment pe un cluster de dezvoltare MySQL.

După cum sa menționat deja, documentație oficială acoperă problema actualizării serverelor MySQL cu replici. Concluzia este că mai întâi ar trebui să actualizați toate replicile (slave), deoarece MySQL 8 se poate replica dintr-o versiune master 5.7. O anumită dificultate constă în faptul că folosim modul maestru <-> maestru, când masterul de la distanță este în modul read-only. Adică, de fapt, traficul de luptă merge către un centru de date, iar al doilea este unul de rezervă.

Topologia arată astfel:

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

Actualizarea trebuie să înceapă cu replici replica mysql dc 2, mysql master dc 2 и mysql replica dc 1, și se termină cu serverul mysql master dc 1. Pentru a fi mai de încredere, am oprit mașinile virtuale, am făcut instantanee ale acestora și imediat înainte de actualizare am oprit replicarea cu comanda STOP SLAVE. Restul actualizării arată astfel:

  1. Repornim fiecare replica adăugând 3 opțiuni la configurații: skip-networking, skip-slave-start, skip-log-bin. Faptul este că actualizarea bazei de date generează jurnalele binare cu actualizări ale tabelelor de sistem. Aceste directive garantează că nu vor exista modificări ale datelor aplicației din baza de date, iar informațiile despre actualizarea tabelelor de sistem nu vor fi incluse în jurnalele binare. Acest lucru va evita problemele la reluarea replicării.
  2. Instalarea pachetului percona-server-server. Este important de reținut că în MySQL versiunea 8 nu trebuie să rulezi comanda mysqlupgrade după actualizarea serverului.
  3. După o pornire cu succes, repornim din nou serverul - fără parametrii adăugați în primul paragraf.
  4. Ne asigurăm că replicarea funcționează cu succes: verificați SHOW SLAVE STATUS și vezi că tabelele cu contoare din baza de date a aplicației sunt actualizate.

Totul pare destul de simplu: actualizarea dezvoltatorului a avut succes. Ok, puteți programa în siguranță o actualizare nocturnă pentru producție.

Nu a fost nicio tristețe - am actualizat produsul

Cu toate acestea, transferul experienței dezvoltatorilor de succes în producție nu a fost lipsit de surprize.

Din fericire, procesul de actualizare în sine începe cu replici, așa că atunci când am întâmpinat dificultăți, am oprit lucrul și am restaurat replica din instantaneu. Investigarea problemelor a fost amânată până a doua zi dimineață. Jurnalele conțineau următoarele intrări:

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

Cercetarea arhivelor diferitelor liste de corespondență de pe Google a condus la înțelegerea că această problemă apare din cauza Bug MySQL. Deși aceasta este mai probabil o eroare de utilitate mysqlcheck и mysqlsh.

Se pare că MySQL a schimbat modul în care reprezintă datele pentru câmpurile zecimale (int, tinyint etc.), așa că mysql-server folosește o modalitate diferită de a le stoca. Dacă baza ta de date inițial a fost în versiunea 5.5 sau 5.1 și apoi ați actualizat la 5.7, atunci poate fi necesar să faceți OPTIMIZE pentru unele mese. Apoi MySQL va actualiza fișierele de date, transferându-le în formatul de stocare curent.

Puteți verifica acest lucru și cu utilitarul 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',
...

Dacă field_type Dacă îl aveți egal cu 0, atunci tipul vechi este utilizat în tabel - trebuie să efectuați OPTIMIZE. Cu toate acestea, dacă valoarea este 246, aveți deja un tip nou. Mai multe informații despre tipuri pot fi găsite în cod.

Mai mult, în acest bug Luăm în considerare al doilea motiv posibil, care ne-a ocolit: absența tabelelor InnoDB în tabelul de sistem INNODB_SYS_TABLESPACES, dacă acestea, tabele, au fost create în versiunea 5.1. Pentru a evita problemele la actualizare, puteți utiliza script SQL atașat.

De ce nu am avut astfel de probleme la dev? Baza de date este copiată periodic acolo din producție - astfel, tabelele sunt recreate.

Din păcate, pe o bază de date mare care funcționează, nu veți putea doar să luați și să executați un universal OPTIMIZE. percona-toolkit va ajuta aici: utilitarul pt-online-schema-change este excelent pentru operațiunea online OPTIMIZE.

Planul actualizat arăta astfel:

  1. Optimizați toate tabelele.
  2. Actualizați bazele de date.

Pentru a o verifica și, în același timp, pentru a afla ora actualizării, am dezactivat una dintre replici și am rulat următoarea comandă pentru toate tabelele:

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

Tabelele sunt actualizate fără blocări lungi datorită faptului că utilitarul creează un nou tabel temporar în care copiază datele din tabelul principal. În momentul în care ambele mese sunt identice, masa originală este blocată și înlocuită cu cea nouă. În cazul nostru, o rulare de test a arătat că va dura aproximativ o zi pentru a actualiza toate tabelele, dar copierea datelor a cauzat prea multă încărcare pe discuri.

Pentru a evita acest lucru, în producție am adăugat argumentul la comandă --sleep cu o valoare de 10 - acest parametru ajustează durata de așteptare după transferul unui lot de date într-un nou tabel. În acest fel, puteți reduce sarcina dacă aplicația care rulează real necesită timp de răspuns.

După efectuarea optimizării, actualizarea a avut succes.

... dar nu complet!

La o jumătate de oră de la actualizare, clientul a apărut cu o problemă. Baza de date a funcționat foarte ciudat: periodic au început resetează conexiunea. Iată cum arăta în monitorizare:

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

Captura de ecran arată un grafic din dinte de ferăstrău datorită faptului că unele dintre firele de execuție ale serverului MySQL s-au prăbușit periodic cu o eroare. Au apărut erori în aplicație:

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

O inspecție rapidă a jurnalelor a arătat că demonul mysqld nu a putut obține resursele necesare de la sistemul de operare. În timp ce sortăm erorile, am descoperit în sistem fișierele de politică de apariție „orfane”.:

# 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

Aceste fișiere au fost create la actualizarea la MySQL 5.7 acum câțiva ani și aparțin unui pachet eliminat. Ștergerea fișierelor și repornirea serviciului apparmor a rezolvat 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

în concluzie

Orice operațiune, chiar și cea mai simplă, poate duce la probleme neașteptate. Și chiar și a avea un plan bine gândit nu garantează întotdeauna rezultatul așteptat. Acum, toate planurile de actualizare pe care le are echipa noastră includ și curățarea obligatorie a fișierelor inutile care ar fi putut apărea ca urmare a acțiunilor recente.

Și cu această creativitate grafică nu foarte profesională, aș dori să îi mulțumesc enorm lui Percona pentru produsele sale excelente!

Actualizarea MySQL (Server Percona) de la 5.7 la 8.0

PS

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu