Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Pokrok sa nezastavuje, preto sa dôvody na aktualizáciu na aktuálne verzie MySQL stávajú čoraz významnejšími. Nedávno sme v jednom z našich projektov došli k okamihu, kedy bolo potrebné aktualizovať pohodlné klastre Percona Server 5.7 na 8. verziu. Všetko sa to odohralo na platforme Ubuntu Linux 16.04. Ako vykonať takúto operáciu s minimálnym výpadkom a s akými problémami sme sa stretli pri aktualizácii — čítajte v tomto článku.

Príprava

Akákoľvek aktualizácia servera databáz pravdepodobne súvisí s prekonfigurovaním databázy: zmenami požiadaviek na limity systémových zdrojov a opravou konfigurácií databázy, ktoré je potrebné očistiť od zastaraných direktív.

Pred aktualizáciou sa určite obrátime na oficiálnu dokumentáciu:

A zostavíme plán akcií:

  1. Opraviť konfiguračné súbory, odstrániť zastarané direktívy.
  2. Skontrolovať kompatibilitu nástrojmi.
  3. Aktualizovať slave databázy inštalovaním balíka percona-server-server.
  4. Aktualizovať master, nainštalovať ten istý balík.

Podrobne rozoberieme každý bod plánu a pozrieme sa, čo by sa mohlo pokaziť.

DÔLEŽITÉ! Procedúra aktualizácie MySQL klastru založeného na Galera má svoje špecifiká, ktoré nie sú v článku popísané. Nenechávajte sa zmiasť touto inštrukciou v takom prípade.

Časť 1: Kontrola konfigurácií

V 8. verzii MySQL odstránili query_cache. V skutočnosti bol považovaný za zastaraný už vo verzii 5.7, ale teraz je úplne odstránený. Zodpovedajúco je potrebné odstrániť súvisiace direktívy. A na caching dotazov je teraz možné použiť externé nástroje — napríklad ProxySQL.

Taktiež v konfiguračnom súbore sa našli zastarané direktívy o innodb_file_format. Ak v MySQL 5.7 existovala možnosť výberu formátu InnoDB, 8. verzia už pracuje iba s formátom Barracuda.

Náš výsledok — odstránenie nasledujúcich direktív:

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

Na kontrolu využijeme Docker obraz Percona Server. Konfiguráciu servera umiestnime do adresára mysql_config_test, a vedľa vytvoríme adresáre pre dáta a logy. Príklad testu konfigurácie 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

Výsledok: buď v logoch Dockeru, alebo v adresári s logmi — v závislosti od vašich konfigurácií — sa objaví súbor, v ktorom budú opísané problematické direktívy.

Toto sme mali my:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] Syntax 'expire-logs-days' je zastaraný a bude odstránený v budúcom vydaní. Prosím, používajte namiesto toho binlog_expire_logs_seconds.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' je momentálne aliasom pre znakový súbor UTF8MB3, ale v budúcom vydaní bude aliasom pre UTF8MB4. Prosím, zvážte používanie UTF8MB4, aby ste boli jednoznační.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' je kolácia zastaraného znakového súboru UTF8MB3. Prosím, zvážte používanie UTF8MB4 s vhodnou koláciou.

Takže sme sa museli ešte zaoberať kódovaniami a nahradiť zastaranú direktívu expire-logs-days.

Časť 2: Kontrola fungujúcich inštalácií

V dokumentácii k aktualizácii sú 2 nástroje na kontrolu databázy na kompatibilitu. Ich použitie pomáha administrátorovi overiť kompatibilitu existujúcej dátovej štruktúry.

Začneme s klasickým nástrojom mysqlcheck. Stačí jednoducho spustiť:

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

Ak neboli zistené žiadne problémy, nástroj skončí s kódom 0:

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Okrem toho, v moderných verziách MySQL je k dispozícii nástroj mysql-shell (v prípade Percona je to balík percona-mysql-shell). Je to náhrada klasického klienta mysql a spája funkcie klienta, editora SQL kódu a nástroje na administráciu MySQL. Na kontrolu servera pred aktualizáciou môžete cez ňu vykonať nasledujúcu príkaz:

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

A tu sú poznámky, ktoré sme dostali:

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Celkovo nič kritické — iba upozornenia na kódovania (pozri nižšie). Celkový výsledok vykonania:

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Rozhodli sme sa, že aktualizácia by mala prebehnúť bez problémov.

Poznámka k upozorneniam vyššie, ktoré naznačujú problémy s kódovaniami. Ide o to, že UTF-8 v MySQL donedávna nebola "pravou" UTF-8, pretože uchovávala iba 3 bajty namiesto 4. V MySQL 8 to konečne rozhodli opraviť: alias utf8 čoskoro bude viesť na kódovanie utf8mb4, a staré stĺpce v tabuľkách sa stanú utf8mb3. V budúcnosti bude kódovanie utf8mb3 odstránené, ale nie v tejto verzii. Preto sme sa rozhodli opraviť kódovania už na bežiacej inštalácii DBMS po jej aktualizácii.

Časť 3: Aktualizácia serverov

Čo sa môže pokaziť, keď máme taký skvelý plán? ... Plne chápeme, že detaily sa vždy môžu objaviť, prvý experiment sme vykonali na dev-klátri MySQL.

Ako už bolo spomenuté, oficiálna dokumentácia rieši problém aktualizácie serverov MySQL s replikami. Základná myšlienka spočíva v tom, že najskôr by sa mali aktualizovať všetky repliky (slave), pretože MySQL 8 dokáže replikovať z mastera verzie 5.7. Určitá zložitosť spočíva v tom, že používame režim master master, keď vzdialený master je v režime read-only. To znamená, že faktický prevádzkový traffic prichádza do jedného datacentra, zatiaľ čo druhé slúži ako záložné.

Topológia vyzerá nasledovne:

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Aktualizácia by sa mala začať od repliky mysql replica dc 2, mysql master dc 2 a mysql replica dc 1, a skončiť serverom mysql master dc 1. Pre väčšiu spoľahlivosť sme zastavili virtuálne stroje, urobili ich snapshoty, a tesne pred aktualizáciou sme zastavili replikáciu príkazom STOP SLAVE. Inak aktualizácia vyzerá takto:

  1. Každú repliku reštartujeme a pridáme do konfigurácií 3 možnosti: skip-networking, skip-slave-start, skip-log-bin. Dôvodom je, že aktualizácia databázy generuje binárne logy aktualizácie systémových tabuliek. Tieto direktívy zaručujú, že v databáze nedôjde k zmene dát aplikácie a do binárnych logov sa nedostane informácia o aktualizácii systémových tabuliek. To pomôže vyhnúť sa problémom pri obnovení replikácie.
  2. Inštalujeme balík percona-server-server. Je dôležité poznamenať, že v MySQL 8 nie je potrebné spustiť príkaz mysqlupgrade po aktualizácii servera.
  3. Po úspešnom štarte ešte raz reštartujeme server — už bez parametrov, ktoré sa pridali v prvom bode.
  4. Ubezpečujeme sa, že replikácia úspešne funguje: kontrolujeme SHOW SLAVE STATUS a sledujeme, že sa aktualizujú tabuľky so čítačmi v databáze aplikácie.

Všetko to vyzerá dosť jednoducho: aktualizácia dev prebehla úspešne. Ok, môžeme pokojne plánovať nočnú aktualizáciu pre produkciu.

Nebolo žiadnych smútení — prod sme aktualizovali

Avšak prenesenie úspešného skúsenosti z dev na produkciu sa nezaobišlo bez prekvapení.

Našťastie, samotný proces aktualizácie sa začína od replik, a preto, keď sme narazili na problémy, zastavili sme práce a obnovili replikáciu zo snapshotu. Preskúmanie problémov sme presunuli na nasledujúce ráno. V logoch sa objavili nasledujúce záznamy:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] tabulka: t1 má 19 stĺpcov, ale InnoDB slovník má 20 stĺpcov
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Chyba pri oprave SE údajov pre db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Nepodarilo sa naplniť DD tabuľky.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Prerušenie

Skúmanie archívov rôznych e-mailových distribúcií v Google viedlo k poznaniu, že takéto problémy vznikajú z chyby MySQL. Hoci je to skôr chyba utilít mysqlcheck a mysqlsh.

Ukazuje sa, že v MySQL zmenili spôsob prezentácie údajov pre desaťinné polia (int, tinyint a pod.), preto sa vo vnútri mysql-serveru používa iný spôsob ich ukladania. Ak vaša databáza pôvodne bola vo verzii 5.5 alebo 5.1 a potom ste sa aktualizovali na 5.7, možno je potrebné vykonať OPTIMIZE pre niektoré tabuľky. Vtedy MySQL aktualizuje súbory s údajmi, pričom ich prevedie na aktuálny formát ukladania.

Taktiež to môžete skontrolovať pomocou utilíty mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # formát poľa
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'your_decimal_column',
...

Ak field_type je rovný 0, tabuľka používa starý typ — treba vykonať OPTIMIZE. Avšak, ak je hodnota 246 — už máte nový typ. Podrobnosti o typoch nájdete v kóde.

Navyše, v danej chybe sa zvažuje druhá možná príčina, ktorá nás obíde, — nedostatok InnoDB tabuliek v systémovej tabuľke INNODB_SYS_TABLESPACES, ak sa tabuľky vytvorili vo verzii 5.1. Aby ste predišli problémom pri aktualizácii, môžete využiť priložený SQL skript.

Prečo teda nemáme takéto problémy na dev? Databáza sa tam periodicky kopíruje z produkcie — týmto spôsobom, tabuľky sa znova vytvárajú.

Bohužiaľ, na skutočne fungujúcej veľkej databáze nebude možné jednoducho zobrať a vykonať úplnú OPTIMIZE. Tu pomôže percona-toolkit: na operáciu online OPTIMIZE je výborná utilita pt-online-schema-change.

Aktualizovaný plán sa zdal takýto:

  1. Vykonať optimalizáciu všetkých tabuliek.
  2. Vykonať aktualizáciu databáz.

Aby sme to skontrolovali a zistili čas aktualizácie, odpojili sme jednu replikáciu a pre všetky tabuľky spustili nasledujúcu príkaz:

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

Aktualizácia tabuliek prebieha bez dlhých blokácií, pretože utilita vytvára novú dočasnú tabuľku, do ktorej kopíruje dáta z hlavnej tabuľky. V momente, keď sú obe tabuľky identické, pôvodná tabuľka sa zablokuje a nahradí novou. V našom prípade testovacie spustenie ukázalo, že na aktualizáciu všetkých tabuliek bude potrebných približne 24 hodín, ale kopírovanie dát spôsobovalo príliš veľké zaťaženie diskov.

Aby sme tomu predišli, na produkcii sme k príkazu pridali argument --sleep s hodnotou 10 — tento parameter reguluje dĺžku čakania po presunutí dávky dát do novej tabuľky. Takto môžeme znížiť zaťaženie, ak je reálne spustená aplikácia náročná na čas odozvy.

Po vykonaní optimalizácie prebehla aktualizácia úspešne.

… ale nie do konca!

Už polhodinu po aktualizácii prišiel klient s problémom. Databáza pracovala veľmi zvláštne: občas začali resetovanie pripojení. Takto to vyzeralo v monitoringu:

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

Na snímke je viditeľná zubatozú časová os, spojená s tým, že časť vlákien MySQL servera občas padala s chybou. V aplikácii sa objavili chyby:

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

Rýchly pohľad na logy odhalil, že démon mysqld nemohol získať potrebné zdroje od operačného systému. Po skúmaní chýb sme objavili v systéme "opustené" súbory politík apparmor:

# 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

Tieto súbory vznikli pri aktualizácii na MySQL 5.7 pred pár rokmi a patria vzdialenému balíčku. Odstránenie súborov a reštartovanie služby apparmor vyriešilo problém:

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

Na záver

Akákoľvek, aj tá najjednoduchšia operácia, môže viesť k neočakávaným problémom. A aj existencia premysleného plánu nezaručuje vždy očakávaný výsledok. Teraz do akýchkoľvek plánov aktualizácie naša tím zahrňuje aj povinné čistenie nadbytočných súborov, ktoré mohli vzniknúť v dôsledku posledných akcií.

A za toto nepáčilenské grafické dielo by som chcel vyjadriť obrovské poďakovanie spoločnosti Percona za ich vynikajúce produkty!

Aktualizácia MySQL (Percona Server) z 5.7 na 8.0

P.S.

Prečítajte si tiež na našom blogu:

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster