
Progresul nu stă pe loc, așa că motivele pentru a face upgrade la versiunile actuale de MySQL devin din ce în ce mai convingătoare. Nu cu mult timp în urmă, într-unul dintre proiectele noastre a sosit momentul să actualizăm confortabilele clustere Percona Server 5.7 la versiunea 8. Totul s-a întâmplat pe platforma Ubuntu Linux 16.04. Cum să efectuezi o astfel de operațiune cu o întrerupere minimă și cu ce probleme ne-am confruntat în timpul actualizării - citiți în acest articol.
Pregătire
Orice actualizare a serverului de baze de date este, cel mai probabil, legată de reconfigurarea bazei de date: schimbări în cerințele privind limitele resurselor de sistem și corectarea configurațiilor bazei de date, care trebuie curățate de directivele învechite.
Înainte de actualizare, ne vom consulta cu siguranță documentația oficială:
- ;
- ;
- ;
- .
Și vom elabora un plan de acțiune:
- Corectarea fișierelor de configurare, eliminând directivele învechite.
- Verificarea compatibilității cu utilitarele.
- Actualizarea bazelor slave, instalând pachetul
percona-server-server. - Actualizarea masterului, instalând același pachet.
Să discutăm fiecare punct din plan și să vedem ce ar putea decurge prost.
IMPORTANT! Procedura de actualizare a clusterului MySQL bazat pe Galera are propriile sale subtilități, care nu sunt descrise în acest articol. Nu ar trebui să folosiți această instrucțiune în astfel de cazuri.
Partea 1: Verificarea configurațiilor
În versiunea 8 de MySQL, au fost eliminate query_cache. De fapt, acesta a fost începând cu versiunea 5.7, dar acum este complet Prin urmare, trebuie eliminate directivele asociate. Iar pentru cache-ul interogărilor se pot folosi acum instrumente externe — de exemplu, .
De asemenea, în configurare am găsit directive învechite referitoare la innodb_file_format. Dacă în MySQL 5.7 existau opțiuni de alegere a formatului InnoDB, versiunea 8 funcționează .
Rezultatul nostru — eliminarea următoarelor directive:
-
query_cache_type,query_cache_limitșiquery_cache_size; -
innodb_file_formatșiinnodb_file_format_max.
Pentru verificare, vom folosi o imagine Docker a Percona Server. Configurația serverului o vom plasa în directorul mysql_config_test, iar lângă acesta vom crea directoare pentru date și loguri. Exemplu de testare a configurației 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-centosConcluzie: fie în logurile Docker, fie în directorul cu loguri — î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] Sintaxa 'expire-logs-days' este deprecata și va fi eliminată într-o versiune viitoare. Vă rugăm să folosiți în schimb binlog_expire_logs_seconds.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' este în prezent un alias pentru setul de caractere UTF8MB3, dar va fi un alias pentru UTF8MB4 într-o versiune viitoare. Vă rugăm să luați în considerare utilizarea UTF8MB4 pentru a evita ambiguitatea.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' este o collation a setului de caractere deprecate UTF8MB3. Vă rugăm să luați în considerare utilizarea UTF8MB4 cu o collation adecvată în schimb. Astfel, a trebuit să ne ocupăm de codificări și să înlocuim directiva deprecata expire-logs-days.
Partea 2: Verificarea instalărilor funcționale
În documentația de actualizare există 2 utilitare pentru a verifica baza de date pentru compatibilitate. Utilizarea lor ajută administratorul să verifice compatibilitatea structurii de date existente.
Să începem cu utilitarul clasic mysqlcheck. Este suficient să rulăm:
mysqlcheck -u root -p --all-databases --check-upgradeDacă nu sunt descoperite probleme, utilitarul se va încheia cu codul 0:

În plus, în versiunile moderne de MySQL este disponibil utilitarul (în cazul Percona este pachetul percona-mysql-shell). Acesta este un substitut pentru clientul clasic mysql și combină funcțiile clientului, editorului de cod SQL și instrumente de administrare MySQL. Pentru a verifica serverul înainte de actualizare, puteți rula următoarea comandă prin intermediu:
mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=\/etc\/mysql\/my.cnfIată ce observații am primit:

În general, nimic critic — doar avertismente despre codificări. (vezi mai jos)Rezultatul general al execuției:

Am decis că actualizarea ar trebui să decurgă fără probleme.
Observația privind avertismentele de mai sus, indicând probleme cu codificările. Este vorba că UTF-8 în MySQL până de curând , deoarece stoca doar 3 byte în loc de 4. În MySQL 8 s-a decis în sfârșit : aliasul utf8 va deveni în curând codificarea utf8mb4, iar coloanele vechi din tabele vor deveni utf8mb3.În viitor, codificarea utf8mb3. va fi eliminată, dar nu în această versiune. Așadar, am decis să corectăm codificările deja pe instalarea activă a SGBD-ului, după actualizarea acesteia.
Partea 3: Actualizarea serverelor
Ce ar putea merge prost când ai un plan atât de strălucit?.. Înțelegând perfect că nuanțele apar mereu, primul experiment l-am efectuat pe un cluster de dev MySQL.
Așa cum s-a menționat anterior, abordează întrebarea actualizării serverelor MySQL cu replici. Ideea de bază este că mai întâi ar trebui actualizate toate replicile (slave), deoarece MySQL 8 poate replica de la un master de versiune 5.7. O dificultate constă în faptul că utilizăm modul master master, când master-ul de la distanță se află în modul read-only. Asta înseamnă că, de fapt, traficul operațional ajunge într-un data center, iar al doilea este rezervă.
Topology looks as follows:

Actualizarea trebuie să înceapă cu replicile mysql replica dc 2, mysql master dc 2 și mysql replica dc 1, iar finalizarea să fie cu serverul mysql master dc 1. Pentru o mai mare fiabilitate, am oprit mașinile virtuale, am creat snapshot-uri, iar imediat înainte de actualizare am oprit replicarea cu comanda STOP SLAVE. În rest, actualizarea arată astfel:
- Fiecare replică se repornește, adăugând în configurații 3 opțiuni:
skip-networking,skip-slave-start,skip-log-bin. Problema este că actualizarea bazei generează jurnale binare cu actualizarea tabelelor de sistem. Aceste directive garantează că nu va exista modificarea datelor aplicației în baza de date și că informațiile despre actualizarea tabelelor de sistem nu vor ajunge în jurnalele binare. Acest lucru va evita problemele la reluarea replicării. - Instalăm pachetul
percona-server-server. Este important de menționat că în versiunea MySQL 8 nu este necesar să se execute comandamysqlupgradedupă actualizarea serverului. - După pornirea reușită, repornim din nou serverul — deja fără parametrii care au fost adăugați la primul punct.
- Ne asigurăm că replicarea funcționează cu succes: verificăm
SHOW SLAVE STATUSși ne uităm că tabelele cu contoarele din baza de date a aplicației se actualizează.
Totul pare destul de simplu: actualizarea de dev a fost reușită. Ok, putem planifica cu liniște actualizarea nocturnă pentru producție.
Nu au fost probleme - am actualizat prod
Cu toate acestea, transferul experienței de succes de la dev la producție nu a fost lipsit de surprize.
Din fericire, procesul de actualizare începe cu replicile, așa că, întâmpinând dificultăți, am oprit lucrările și am restaurat replica din snapshot. Investigarea problemelor a fost mutată pentru dimineața următoare. În jurnale au apărut următoarele înregistrări:
2020-01-14T21:43:21.500563Z 2 [EROARE] [MY-012069] [InnoDB] tabela: t1 are 19 coloane, dar dicționarul InnoDB are 20 coloane
2020-01-14T21:43:21.500722Z 2 [EROARE] [MY-010767] [Server] Eroare în repararea datelor SE pentru db1.t1
2020-01-14T21:43:24.208365Z 0 [EROARE] [MY-010022] [Server] Eșec la popularea tabelelor DD.
2020-01-14T21:43:24.208658Z 0 [EROARE] [MY-010119] [Server] Abandonare Cercetarea arhivelor diverselor distribuții de e-mail în Google a dus la înțelegerea faptului că această problemă apare din cauza . De fapt, este mai degrabă o eroare a utilitarelor mysqlcheck și mysqlsh.
Se dovedește că, în MySQL, s-a schimbat metoda de prezentare a datelor pentru câmpurile zecimale (int, tinyint etc.), astfel încât în interiorul mysql-server se utilizează o altă metodă de stocare. Dacă baza dvs. de date a fost inițial în versiunea 5.5 sau 5.1 și apoi ați actualizat la 5.7, atunci este posibil să fie necesară efectuarea OPTIMIZE pentru unele tabele. Atunci MySQL va actualiza fișierele cu date, transformându-le în formatul actual de stocare.
De asemenea, acest lucru poate fi verificat cu ajutorul utilitarului mysqlfrm:
mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
'field_length': 8,
'field_type': 246, # formatul câmpului
'field_type_name': 'decimal',
'flags': 3,
'flags_extra': 67,
'interval_nr': 0,
'name': 'you_decimal_column',
... Dacă field_type dacă este egal cu 0, atunci în tabel se utilizează un tip vechi — trebuie să se efectueze OPTIMIZE. Totuși, dacă valoarea este 246 — aveți deja un tip nou. Mai multe informații despre tipuri pot fi găsite în .
Mai mult, în se examinează a doua posibilă cauză, care ne-a ocolit, și anume lipsa tabelelor InnoDB în tabela sistemului INNODB_SYS_TABLESPACES, dacă acestea, tabelele, au fost create în versiunea 5.1. Pentru a evita problemele la actualizare, se poate utiliza .
De ce nu am avut astfel de probleme pe dev? Baza este copiată periodic din producție — astfel, tabelele sunt recreați.
Din păcate, pe o bază de date mare care este în funcțiune nu se poate pur și simplu să luați și să efectuați o OPTIMIZE. Aici percona-toolkit va ajuta: pentru operația online OPTIMIZE, utilitarul pt-online-schema-change este perfect.
Planul actualizat arată astfel:
- Efectuarea optimizării tuturor tabelelor.
- Efectuarea actualizării bazelor de date.
Pentru a verifica acest lucru și a afla timpul de actualizare, am oprit una dintre replici, iar pentru toate tabelele am rulat următoarea comandă:
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=t1Actualizarea tabelelor se face fără blocaje prelungite, deoarece utilitarul creează un nou tabel temporar în care copiază datele din tabelul principal. În momentul în care ambele tabele sunt identice, tabelul original este blocat și înlocuit cu noul. În cazul nostru, testul a arătat că pentru actualizarea tuturor tabelelor este necesară aproximativ o zi, însă copierea datelor a provocat o încărcare prea mare pe discuri.
Pentru a evita acest lucru, pe producție am adăugat un argument echipei --sleep cu valoarea 10 — acest parametru reglează durata de așteptare după transferul unui lot de date în noul tabel. Astfel se poate reduce încărcarea, dacă aplicația reală este exigentă în ceea ce privește timpul de răspuns.
După terminarea optimizării, actualizarea a avut succes.
… dar nu complet!
La doar jumătate de oră după actualizare, clientul a venit cu o problemă. Baza de date se comporta foarte ciudat: periodic începeau resetări ale conexiunilor. Iată cum arăta în monitorizare:

În captura de ecran se poate observa un grafic în formă de dinți de fierăstrău, legat de faptul că o parte din thread-urile serverului MySQL cădeau periodic cu o eroare. În aplicație au apărut erori:
[PDOException] SQLSTATE[HY000] [2002] Conexiune refuzatăO examinare rapidă a jurnalelor a relevat că demonul mysqld nu putea obține resursele necesare de la sistemul de operare. Analizând erorile, am descoperit în sistem fișierele de politicile apparmor "fără stăpân":
# 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 amd64Aceste fișiere s-au format în urma actualizării la MySQL 5.7 acum câțiva ani și aparțin unui pachet eliminat. Ștergerea fișierelor și repornirea serviciului apparmor au 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. Chiar și existența unui plan bine gândit nu garantează întotdeauna rezultatul dorit. Acum, în orice plan de actualizare a echipei noastre este inclusă și curățarea fișierelor inutile, care ar fi putut apărea în urma acțiunilor anterioare.
Și prin această lucrare grafică nu foarte profesionistă, aș dori să mulțumesc companiei Percona pentru produsele lor excelente!

P.S.
Citiți și în blogul nostru:
- «»;
- «»;
- «»;
- «»;
- «».
Sursa: habr.com
