MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Progress neapstājas, tāpēc iemesli atjaunoties uz jaunākajām MySQL versijām kļūst arvien svarīgāki. Pirms neilga laika vienā no mūsu projektiem pienāca laiks atjaunot ērtos Percona Server 5.7 klasterus uz 8. versiju. Tas notika platformā Ubuntu Linux 16.04. Kā veikt šādu operāciju ar minimālu dīkstāvi un ar kādām problēmām mēs saskārāmies atjaunināšanas procesā - lasiet šajā rakstā.

Sagatavošana

Jebkura datu bāzes servera atjaunināšana, visticamāk, saistīta ar datu bāzes pārvērtēšanu: izmaiņām prasībās pēc sistēmas resursu ierobežojumiem un konfigurācijas failu labojumiem, no kuriem nepieciešams izņemt novecojušos direktīvus.

Pirms atjaunināšanas mēs noteikti atsauksimies uz oficiālo dokumentāciju:

Un izveidosim rīcības plānu:

  1. Izlabot konfigurācijas failus, iznīcinot novecojušās direktīvas.
  2. Pārbaudīt savietojamību ar rīkiem.
  3. Atjaunināt slave-datubāzes, instalējot pakotni percona-server-server.
  4. Atjaunināt galveno serveri, instalējot to pašu pakotni.

Pārskatīsim katru plāna punktu un paskatīsimies, kas varētu noiet greizi.

SVARĪGI! MySQL klastera atjaunināšanas procedūra uz Galera bāzes ir sarežģītāka, nekā aprakstīts rakstā. Šo instrukciju nevajadzētu izmantot šajā gadījumā.

1. daļa: Konfigurāciju pārbaude

MySQL 8. versijā tika izņemts query_cache. Vispārīgi runājot, tas tika atzīts par novecojušu jau 5.7 versijā, bet tagad tas ir pavisam izņemts. Attiecīgi, nepieciešams noņemt saistītās direktīvas. Savukārt, lai kešotu vaicājumus, tagad var izmantot ārējus rīkus — piemēram, ProxySQL.

Tāpat konfigurācijā atradām novecojušās direktīvas par innodb_file_format. Ja MySQL 5.7 bija iespēja izvēlēties InnoDB formātu, tad 8. versija darbotos tikai ar Barracuda formātu.

Mūsu rezultāts — novēršana sekojošām direktīvām:

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

Pārbaudes veikšanai izmantosim Docker tēlu Percona Server. Servera konfigurāciju ievietosim direktorijā mysql_config_test, blakus izveidosim direktorijas datiem un žurnāliem. Konfigurācijas pārbaudes piemērs 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

Rezultāts: vai nu Docker žurnālos, vai žurnālu direktorijā — atkarībā no jūsu konfigurācijām — parādīsies fails, kurā būs aprakstītas problemātiskās direktīvas.

Lūk, kas mums bija:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] Sintakse 'expire-logs-days' ir novecojusi un tiks noņemta nākamajā versijā. Lūdzu, izmantojiet binlog_expire_logs_seconds vietā.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' šobrīd ir alias rakstzīmju kopai UTF8MB3, bet nākotnē būs alias UTF8MB4. Lūdzu, apsveriet iespēju izmantot UTF8MB4, lai nebūtu neskaidrību.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' ir novecojusī rakstzīmju kopas UTF8MB3 sakārtošanas noteikums. Lūdzu, apsveriet iespēju izmantot UTF8MB4 ar atbilstošu sakārtošanu.

Tādējādi nācās vēl reiz izpētīt kodējumus un aizstāt novecojušo direktīvu expire-logs-days.

2. daļa: Darbojošo instalāciju pārbaude

Atjaunināšanas dokumentācijā ir 2 utilītas datu bāzes saderības pārbaudei. To izmantošana palīdz administratoram pārbaudīt esošo datu struktūras saderību.

Sāksim ar klasisko utilītu mysqlcheck. Pietiek vienkārši to palaist:

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

Ja problēmas netiek atrastas, utilīta pabeigs darbu ar kodu 0:

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Turklāt mūsdienu MySQL versijās ir pieejama utilīta mysql-shell (Percona gadījumā tas ir pakotne percona-mysql-shell). Tā ir aizvietotājs klasiskajam mysql klientam un apvieno klienta, SQL koda redaktora un MySQL administrēšanas rīku funkcijas. Servera pārbaudei pirms atjaunināšanas var caur to izpildīt šādu komandu:

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

Un lūk, kādi novērojumi mums bija:

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Kopumā nekas kritisks — tikai brīdinājumi par kodējumiem (skatīt zemāk). Kopējais izpildes rezultāts:

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Mēs nolēmām, ka atjauninājumam nevajadzētu radīt problēmas.

Novērojums par augstāk minētajiem brīdinājumiem liecina par problēmām ar kodējumiem. Problēma ir tāda, ka UTF-8 MySQL līdz nesenam laikam nebija "īstā" UTF-8, jo saglabāja tikai 3 baitus, nevis 4. MySQL 8 to beidzot nolēma labot: alias utf8 drīz tiks novirzīts uz kodēšanu utf8mb4, bet vecās kolonnas tabulās kļūs par utf8mb3. Turpmāk kodējums utf8mb3 tiks izņemts, bet ne šajā izdevumā. Tādēļ mēs nolēmām labot kodējumus jau strādājošajā DB instalācijā, pēc tās atjaunināšanas.

3. daļa: Serveru atjaunināšana

Ko gan var noiet greizi, kad ir tik lielisks plāns?.. Labi apzinoties, ka nianses vienmēr notiek, pirmo eksperimentu mēs veicām dev-klasterī MySQL.

Kā jau tika minēts, oficiālā dokumentācija apgaismo jautājumu par MySQL serveru atjaunināšanu ar replikām. Jāatzīmē, ka vispirms ir jāatjaunina visas replikas (slave), jo MySQL 8 spēj replikēties no 5.7 versijas meisra. Dažas grūtības rodas, jo mēs izmantojam režīmu master master, kad attālinātais meisrs atrodas read-only. Tātad faktiski darījumu satiksme notiek vienā datu centrā, bet otrais ir rezerves.

Topoloģija izskatās šādi:

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Atjaunināšana jāuzsāk ar replikām mysql replica dc 2, mysql master dc 2 un mysql replica dc 1, un jābeidz ar serveri mysql master dc 1. Lai palielinātu drošību, mēs apstādinājām virtuālās mašīnas, izveidojām to momentuzņēmumus, un tieši pirms atjaunināšanas apstādinājām replikāciju ar komandu STOP SLAVE. Vispārējais atjauninājums izskatās šādi:

  1. Katru repliku pārstartējam, pievienojot konfigurācijām 3 opcijas: skip-networking, skip-slave-start, skip-log-bin. Tas ir tāpēc, ka datu bāzes atjaunināšana ģenerē bināros žurnālus ar sistēmu tabulu atjaunināšanu. Šie direktīvi garantē, ka datu bāzē nebūs izmaiņu lietojumprogrammās, un binārajos žurnālos neiekļūs informācija par sistēmu tabulu atjaunināšanu. Tas novērsīs problēmas replikācijas atjaunošanā.
  2. Instalējam pakotni percona-server-server. Ir svarīgi atzīmēt, ka MySQL 8 versijā nees jāizpilda komanda mysqlupgrade pēc servera atjaunināšanas.
  3. Pēc veiksmīgas palaišanas vēlreiz pārstartējam serveri — jau bez pirmajā punktā pievienotajām parametram.
  4. Pārbaudām, vai replikācija darbojas veiksmīgi: pārbaudām SHOW SLAVE STATUS un skatāmies, ka tabulas ar skaitītājiem lietojumprogrammas datu bāzē tiek atjauninātas.

Viss izskatās diezgan vienkārši: dev atjauninājums izdevās veiksmīgi. Labi, varam mierīgi plānot nakts atjauninājumu produkcijai.

Nebija bēdu — prod mēs atjauninājām

Tomēr veiksmīgā dev pieredze pārsūtīšanā uz produkciju nesanāca bez pārsteigumiem.

Par laimi, pats atjaunināšanas process sākas ar replikām, tāpēc, sastopot grūtības, mēs apstādinājām darbus un atjauninājām repliku no momentuzņēmuma. Problēmu izpēte tika pārcelta uz nākamo rītu. Dienasgrāmatās atradām šādas ierakstu:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] tabula: t1 satur 19 kolonnām, bet InnoDB vārdnīcā ir 20 kolonnas
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Kļūda labojot SE datus db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Neizdevās aprakstīt DD tabulas.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Atceļ

Pētījums par dažādu pasta sūtījumu arhīviem Google noveda pie izpratnes, ka tāda problēma rodas dēļ MySQL kļūdas. Tomēr, drīzāk tas pat ir kļūda rīkos mysqlcheck un mysqlsh.

Izrādās, ka MySQL ir mainījusi datu attēlošanas veidu desmitu lauku (int, tinyint u.c.) dēļ, tāpēc mysql-server iekšienē tiek izmantots cits veids to glabāšanai. Ja jūsu datu bāze pirmotnēji bija versijā 5.5 vai 5.1, un tad jūs atjauninājāt uz 5.7, tad, iespējams, ir nepieciešams veikt OPTIMIZE dažām tabulām. Tad MySQL atjauninās datu failus, pārvēršot tos aktuālajā glabāšanas formātā.

To var pārbaudīt arī ar rīku mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # lauka formāts
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

Ja field_type ja jums ir 0, tad tabulā tiek izmantots vecais tips — jāveic OPTIMIZE. Tomēr, ja ir vērtība 246 — jums jau ir jaunais tips. Sīkāk par tipiem var iepazīties kode.

Turklāt šajā kļūdā apspriesta otra iespējamā problēma, kas mūs apgāja — tas ir InnoDB tabulu trūkums sistēmas tabulā INNODB_SYS_TABLESPACES, ja šīs tabulas tika izveidotas versijā 5.1. Lai novērstu problēmas atjaunināšanas laikā, var izmantot pievienoto SQL skriptu.

Kāpēc mums neradās šādas problēmas dev? Datu bāze tur regulāri tiek kopēta no produkcijas — tādējādi, tabulas tiek pārradītas.

Diemžēl uz patiesi funkcionējošas lielas datu bāzes nevar vienkārši ņemt un veikt vispārēju OPTIMIZE. Šeit palīdzēs percona-toolkit: online OPTIMIZE operācijai lieliski noder rīks pt-online-schema-change.

Atjauninātais plāns ir kļuvis tāds:

  1. Veikt visu tabulu optimizāciju.
  2. Veikt datu bāzu atjaunināšanu.

Lai to pārbaudītu un vienlaikus uzzinātu atjaunināšanas laiku, mēs atslēdzām vienu no replikām, un visām tabulām palaidām sekojošo komandu:

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

Tabulu atjaunināšana notiek bez ilgiem bloķējumiem, jo utilīta izveido jaunu pagaidu tabulu, kurā nokopē datus no galvenās tabulas. Kad abas tabulas kļūst identiskas, sākotnējā tabula tiek bloķēta un aizvietota ar jauno. Mūsu gadījumā testēšanas laikā tika noskaidrots, ka visu tabulu atjaunināšanai būs nepieciešama aptuveni diena, taču datu kopēšana radīja pārāk lielu slodzi uz diskiem.

Lai to novērstu, ražošanā pievienojām komandai argumentu --sleep ar vērtību 10 — šis parametrs regulē gaidīšanas laiku pēc datu partijas pārcelšanas uz jauno tabulu. Tas ļauj samazināt slodzi, ja reāli palaistā lietotne ir prasīga pret atbildes laiku.

Pēc optimizācijas veikšanas atjaunināšana noritēja veiksmīgi.

… bet ne pilnībā!

Jau pēc pusstundas pēc atjaunināšanas klients nāca ar problēmu. Datu bāze darbojās ļoti dīvaini: periodiski sākās savienojumu atslēgšanas.Tā izskatījās monitoringa laikā:

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

Ekrānšāviņā redzams zobainais grafiks, kas saistīts ar to, ka daļa MySQL servera procesu periodiski sabruka ar kļūdu. Lietotnē parādījās kļūdas:

[PDOException] SQLSTATE[HY000] [2002] Savienojums atteikts

Apskatot žurnālus, atklājās, ka mysqld demons nespēja iegūt nepieciešamos resursus no operētājsistēmas. Pētot kļūdas, mēs atklājām sistēmā ''bezpiederošus'' apparmor politikas failus.:

# 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

Šie faili radās, atjauninot uz MySQL 5.7 pirms pāris gadiem un piederēja noņemtam pakotnei. Failu dzēšana un apparmor pakalpojuma restartēšana atrisināja problēmu:

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

Noslēgumā

Jebkura, pat visvienkāršākā, operācija var novest pie negaidītām problēmām. Un pat labi izstrādāts plāns ne vienmēr garantē gaidīto rezultātu. Tagad jebkurā atjaunināšanas plānā mūsu komandā ir arī obligāta lieko failu attīrīšana, kas varēja rasties pēdējo darbību rezultātā.

Ar šo ne pārāk profesionālo grafisko veidojumu es gribētu izteikt milzīgu pateicību uzņēmumam Percona par viņu izcilajiem produktiem!

MySQL (Percona Server) atjauninājums no 5.7 līdz 8.0

P.S.

Lasiet arī mūsu emuāra rakstos:

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster