Upgrading MySQL (Percona Server) from 5.7 to 8.0

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Napredek ne miruje, zato postajajo razlogi za nadgradnjo na najnovejše različice MySQL vse pomembnejši. Pred kratkim je pri enem od naših projektov prišel čas za nadgradnjo udobnih klasterjev Percona Server 5.7 na 8. različico. Vse to se je dogajalo na platformi Ubuntu Linux 16.04. Kako izvesti to operacijo z minimalnimi ustavitvami in s katerimi težavami smo se srečali pri nadgradnji — preberite v tem članku.

Priprava

Vsaka nadgradnja strežnika baz podatkov bo verjetno povezana s ponovno nastavitvijo baze: spremembami zahtev po omejitvah sistemskih virov in popravkom konfiguracijskih datotek baze, ki jih je treba očistiti od zastarelih direktiv.

Pred nadgradnjo se bomo nujno sklicevali na uradno dokumentacijo:

In pripravili bomo načrt ukrepov:

  1. Popraviti je treba konfiguracijske datoteke, tako da odstranimo zastarele direktive.
  2. Preveriti združljivost s pripomočki.
  3. Nadgraditi slave baze z namestitvijo paketa percona-server-server.
  4. Nadgraditi glavni strežnik in namestiti isti paket.

Razčlenili bomo vsak korak načrta in se prepričali, kaj bi lahko šlo narobe.

Pomembno! Postopek nadgradnje MySQL klasterja na osnovi Galere ima svoje posebnosti, ki niso opisane v tem članku. Te instrukcije ne uporabljajte v tem primeru.

Del 1: Preverjanje konfiguracij

V 8. različici MySQL so odstranili query_cache. V resnici je bil pojavljen kot zastareli že v različici 5.7, zdaj pa je popolnoma odstranjen. Zato je potrebno odstraniti povezane direktive. Za predpomnjenje poizvedb pa lahko zdaj uporabite zunanja orodja — na primer, ProxySQL.

Prav tako so v konfiguraciji našli zastarele direktive o innodb_file_format. Če je bila v MySQL 5.7 možnost izbire formata InnoDB, 8. različica pa deluje samo z formatom Barracuda.

Naš zaključek — odstranitev naslednjih direktiv:

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

Za preverjanje bomo uporabili Docker sliko Percona Server. Konfiguracijo strežnika bomo postavili v imenik mysql_config_test, ob njem pa bomo ustvarili imenike za podatke in dnevniške datoteke. Primer testa konfiguracije 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

Na koncu se bo v dnevnikih Dockerja ali v imeniku z dnevniki, odvisno od vaših nastavitev, pojavil datoteka, v kateri bodo opisane problematične direktive.

Tukaj je, kar smo imeli:

2020-04-03T12:44:19.670831Z 0 [Opozorilo] [MY-011068] [Strežnik] Sintaksa 'expire-logs-days' je zastarela in bo odstranjena v prihodnjem izdanju. Prosimo, da namesto tega uporabite binlog_expire_logs_seconds.
2020-04-03T12:44:19.671678Z 0 [Opozorilo] [MY-013242] [Strežnik] --character-set-server: 'utf8' je trenutno alias za niz znakov UTF8MB3, bo pa v prihodnjem izdanju alias za UTF8MB4. Razmislite o uporabi UTF8MB4, da ne bo zmede.
2020-04-03T12:44:19.671682Z 0 [Opozorilo] [MY-013244] [Strežnik] --collation-server: 'utf8_general_ci' je kolacija zastarelega niza znakov UTF8MB3. Razmislite o uporabi UTF8MB4 z ustrezno kolacijo namesto tega.

Tako smo se morali dodatno ukvarjati s kodiranjem in zamenjati zastarelo direktivo expire-logs-days.

Del 2: Preverjanje delujočih namestitev

V dokumentaciji za nadgradnjo so na voljo 2 orodji za preverjanje baze na skladnost. Njihova uporaba pomaga administratorju, da preveri skladnost obstoječe strukture podatkov.

Začnimo s klasičnim orodjem mysqlcheck. Preprosto ga je treba zagnati:

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

Če težave niso odkrite, se orodje zaključi s kodo 0:

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Poleg tega v sodobnih različicah MySQL obstaja orodje mysql-shell (v primeru Percone je to paket percona-mysql-shell). To je zamenjava klasičnega odjemalca mysql in združuje funkcije odjemalca, urejevalnika SQL kode in orodij za upravljanje MySQL. Za preverjanje strežnika pred nadgradnjo lahko preko nje izvedete naslednji ukaz:

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

In tukaj so ugotovitve, ki smo jih prejeli:

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Na splošno ni nič kritičnega — le opozorila o kodiranju. (см. ниже)Skupni rezultat izvajanja:

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Odločili smo se, da bi morala nadgradnja potekati brez težav.

Opomba o opozorilih zgoraj, ki kažejo na težave s kodiranjem. Dejstvo je, da UTF-8 v MySQL do nedavnega ni bila 'prava' UTF-8,saj je hranila le 3 bajte namesto 4. V MySQL 8 so to končno odpravili:alias utf8 bo kmalu vodil na kodiranje utf8mb4, stari stolpci v tabelah pa bodo postali utf8mb3.V prihodnje bo to kodiranje odstranjeno, vendar ne v tem izdanju. Zato smo se odločili, da popravimo kodiranja že na delujoči namestitvi SGBD, po njeni nadgradnji. utf8mb3. Del 3: Nadgradnja strežnikov

Часть 3: Обновление серверов

Kaj se lahko zgodi, ko imamo tako vrhunski načrt?.. Zavedajoč se, da se vedno pojavijo podrobnosti, smo prvi poskus izpeljali na dev-klasterju MySQL.

Kot smo že omenili, uradna dokumentacija obravnava vprašanje nadgradnje MySQL strežnikov z replikami. Osnovna ideja je, da bi najprej morali nadgraditi vse replikate (slave), saj MySQL 8 lahko replicira z glavnim strežnikom različice 5.7. Nekaj zapletenosti nastane, ker uporabljamo način master master, kjer je oddaljeni glavni strežnik v načinu read-only. To pomeni, da dejanski promet poteka v en datacenter, drugi pa je rezervni.

Topologija je videti takole:

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Nadgradnja se mora začeti z replikami mysql replica dc 2, mysql master dc 2 in mysql replica dc 1, končati pa mora na strežniku mysql master dc 1. Za večjo zanesljivost smo ustavili virtualne stroje, naredili njihove posnetke, in tik pred nadgradnjo ustavili replikacijo z ukazom STOP SLAVE. Ostalo pa izgledam takole:

  1. Vsako repliko znova zaženemo z dodatkom 3 možnosti v konfiguracijo: skip-networking, skip-slave-start, skip-log-bin. Gre za to, da nadgradnja baze generira binarne dnevniške datoteke z obnovitvijo sistemskih tabel. Te direktive zagotavljajo, da v bazi ne bo sprememb podatkov aplikacije ter da v binarne dnevnike ne bo vstopila informacija o obnovitvi sistemskih tabel. To bo preprečilo težave pri ponovnem zagonu replikacije.
  2. Nnamestimo paket percona-server-server. Pomembno je omeniti, da v različici MySQL 8 ne je potrebno zagnati ukaz mysqlupgrade po nadgradnji strežnika.
  3. Po uspešnem zagonu še enkrat znova zaženemo strežnik — že brez parametrov, ki so bili dodani v prvem koraku.
  4. Preverimo, ali replikacija deluje uspešno: preverimo SHOW SLAVE STATUS in si ogledamo, da se tabele s števcem v bazi aplikacije posodabljajo.

Vse to izgleda dovolj preprosto: nadgradnja dev je uspela. Okej, zdaj lahko brez skrbi načrtujemo nočno nadgradnjo za produkcijo.

Nobene skrbi — produkcijo smo nadgradili

Vendar prenos uspešne izkušnje dev na produkcijo ni šel brez presenečenj.

Na srečo se sam postopek nadgradnje začne z replikami, zato smo se ob težavah ustavili in obnovili repliko iz posnetka. Raziskovanje težav smo prestavili na naslednje jutro. V dnevnikih so se pojavili naslednji zapisi:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] таблица: t1 имеет 19 колонок, но в словаре InnoDB 20 колонок
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Сервер] Ошибка при исправлении данных SE для db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Сервер] Не удалось заполнить таблицы DD.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Сервер] Прерывание

Исследование архивов различных почтовых рассылок в Google привело к пониманию, что такая проблема возникает из-за бага MySQL. Хотя скорее это даже баг утилит mysqlcheck in mysqlsh.

Оказывается, в MySQL сменили способ представления данных для десятичных полей (int, tinyint и т.п.), поэтому внутри mysql-server используется другой способ их хранения. Если ваша база данных изначально была в версии 5.5 или 5.1, а затем вы обновлялись до 5.7, то, возможно, требуется произвести OPTIMIZE для некоторых таблиц. Тогда MySQL обновит файлы с данными, переведя их на актуальный формат хранения.

Также это можно проверить утилитой 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',
...

Если field_type у вас равен 0, то в таблице используется старый тип — надо проводить OPTIMIZE. Однако, если стоит значение 246 — у вас уже новый тип. Подробнее с типами можно ознакомиться в kodu.

Более того, в данном баге рассматривается вторая возможная причина, которая обошла нас стороной, — это отсутствие InnoDB-таблиц в системной таблице INNODB_SYS_TABLESPACES, если они, таблицы, создавались в версии 5.1. Чтобы избежать проблем при обновлении, можно воспользоваться приложенным SQL-скриптом.

Почему же у нас не возникло таких проблем на dev? База туда периодически копируется с production — таким образом, таблицы пересоздаются.

К сожалению, на реально работающей большой БД не получится просто взять и выполнить повсеместный OPTIMIZE. Здесь поможет percona-toolkit: для операции online OPTIMIZE отлично подходит утилита pt-online-schema-change.

Обновленный план стал получился таким:

  1. Провести оптимизацию всех таблиц.
  2. Провести обновление баз данных.

Чтобы проверить его и заодно выяснить время обновления, мы отключили одну из реплик, а для всех таблиц запустили следующую команду:

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

Posodobitev tabel se izvaja brez dolgotrajnih zaklenitev, saj orodje ustvari novo začasno tabelo, v katero prenese podatke iz glavne tabele. Ko sta obe tabeli enaki, se izvirna tabela zaklene in nadomesti z novo. V našem primeru je testni zagon pokazal, da bo za posodobitev vseh tabel potrebnih približno 24 ur, vendar je prenos podatkov povzročal preveliko obremenitev na diskih.

Da bi to preprečili, smo na produkciji dodali ekipi argument --sleep z vrednostjo 10 — ta parameter ureja dolžino čakanja po prenosu serije podatkov v novo tabelo. S tem se lahko zmanjša obremenitev, če je dejansko delujoča aplikacija zahtevna glede časa odgovora.

Po optimizaciji je bila posodobitev uspešna.

… ampak ne povsem!

Že pol ure po posodobitvi se je stranka obrnila s težavo. Baza podatkov je delovala zelo nenavadno: občasno so se začela ponovna povezovanja. Tako je to izgledalo v monitoringu:

Upgrading MySQL (Percona Server) from 5.7 to 8.0

Na posnetku zaslona je vidna zobata krivulja, povezano s tem, da so delci strežnika MySQL občasno padali z napako. V aplikaciji so se pojavile napake:

[PDOException] SQLSTATE[HY000] [2002] Povezava zavrnjena

Hitri pregled dnevnikov je pokazal, da daemons mysqld ni mogel pridobiti zahtevanih virov od operacijskega sistema. Ko smo raziskovali napake, smo odkrili v sistemu »brezskrben« datoteke politik 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

Ti datoteke so nastale pri nadgradnji na MySQL 5.7 pred nekaj leti in pripadajo odstranjeni zbirki. Odstranitev datotek in ponovni zagon storitve apparmor je rešila problem:

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

Kakršna koli, celo najpreprostejša operacija, lahko povzroči nepričakovane težave. In celo skrbno načrtovanje ne zagotavlja vedno želenega rezultata. Zdaj vsak načrt posodobitve vključuje tudi obvezno čiščenje odvečnih datotek, ki so lahko nastale kot rezultat prejšnjih dejanj.

In s tem ne prav profesionalnim grafičnim delom bi se rad zahvalil podjetju Percona za njihove odlične proizvode!

Upgrading MySQL (Percona Server) from 5.7 to 8.0

P.S.

Preberite tudi na našem blogu:

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster