Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Fremgangen står ikke stille, så grunnene til å oppgradere til de nyeste versjonene av MySQL blir stadig mer overbevisende. For ikke lenge siden, i et av våre prosjekter, var det på tide å oppdatere de koselige Percona Server 5.7-klyngene til versjon 8. Alt dette skjedde på Ubuntu Linux 16.04-plattformen. Hvordan utføre en slik operasjon med minimal nedetid og hvilke problemer vi møtte under oppdateringen - les i denne artikkelen.

Trening

Enhver oppdatering av databaseserveren er mest sannsynlig assosiert med databaserekonfigurasjon: endringer i krav til begrensninger på systemressurser og korrigering av databasekonfigurasjoner som må fjernes for utdaterte direktiver.

Før vi oppdaterer, vil vi definitivt referere til den offisielle dokumentasjonen:

Og la oss lage en handlingsplan:

  1. Korriger konfigurasjonsfiler ved å fjerne utdaterte direktiver.
  2. Sjekk kompatibilitet med verktøy.
  3. Oppdater slavedatabaser ved å installere pakken percona-server-server.
  4. Oppdater masteren med samme pakke.

La oss se på hvert punkt i planen og se hva som kan gå galt.

VIKTIG! Prosedyren for å oppdatere en MySQL-klynge basert på Galera har sine egne finesser som ikke er beskrevet i artikkelen. Du bør ikke bruke denne instruksjonen i dette tilfellet.

Del 1: Sjekke konfigurasjoner

MySQL ble fjernet i versjon 8 query_cache. Det var han faktisk erklært foreldet tilbake i versjon 5.7, men nå fullstendig slettet. Følgelig er det nødvendig å fjerne de tilhørende direktivene. Og for å bufre forespørsler kan du nå bruke eksterne verktøy - for eksempel, ProxySQL.

Også i konfigurasjonen var det utdaterte direktiver om innodb_file_format. Hvis det i MySQL 5.7 var mulig å velge InnoDB-formatet, fungerer den åttende versjonen allerede bare med Barracuda-format.

Resultatet vårt er fjerning av følgende direktiver:

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

For å sjekke, vil vi bruke Docker-bildet til Percona Server. Vi vil plassere serverkonfigurasjonen i katalogen mysql_config_test, og ved siden av vil vi lage kataloger for data og logger. Percona-serverkonfigurasjonstesteksempel:

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

Bunnlinjen: enten i Docker-loggene eller i katalogen med loggene - avhengig av konfigurasjonene dine - vil en fil vises der de problematiske direktivene vil bli beskrevet.

Her er hva vi hadde:

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.

Dermed trengte vi fortsatt å finne ut kodingene og erstatte det utdaterte direktivet expire-logs-days.

Del 2: Kontroll av fungerende installasjoner

Oppdateringsdokumentasjonen inneholder 2 verktøy for å sjekke databasen for kompatibilitet. Bruken av dem hjelper administratoren med å sjekke kompatibiliteten til den eksisterende datastrukturen.

La oss starte med det klassiske mysqlcheck-verktøyet. Bare kjør:

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

Hvis ingen problemer blir funnet, avsluttes verktøyet med kode 0:

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

I tillegg er et verktøy tilgjengelig i moderne versjoner av MySQL mysql-shell (i tilfelle av Percona er dette pakken percona-mysql-shell). Den er en erstatning for den klassiske mysql-klienten og kombinerer funksjonene til en klient, en SQL-kodeeditor og MySQL-administrasjonsverktøy. For å sjekke serveren før oppdatering, kan du kjøre følgende kommandoer gjennom den:

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

Her er kommentarene vi fikk:

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Generelt ikke noe kritisk - bare advarsler om kodinger (se nedenfor). Samlet utførelsesresultat:

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Vi bestemte oss for at oppdateringen skulle gå uten problemer.

En merknad om advarslene ovenfor som indikerer problemer med koding. Faktum er at UTF-8 i MySQL inntil nylig var ikke "ekte" UTF-8, siden den lagret bare 3 byte i stedet for 4. I MySQL 8 er dette endelig bestemte seg for å fikse det: alias utf8 vil snart føre til koding utf8mb4, og de gamle kolonnene i tabellene blir utf8mb3. Ytterligere koding utf8mb3 vil bli fjernet, men ikke i denne utgivelsen. Derfor bestemte vi oss for å korrigere kodingene allerede på den kjørende DBMS-installasjonen, etter å ha oppdatert den.

Del 3: Serveroppdateringer

Hva kan gå galt når det er en så smart plan?.. For å forstå at nyanser alltid skjer, utførte vi det første eksperimentet på en MySQL-utviklerklynge.

Som allerede nevnt, offisiell dokumentasjon dekker problemet med å oppdatere MySQL-servere med replikaer. Poenget er at du først bør oppdatere alle replikaer (slaver), siden MySQL 8 kan replikere fra en masterversjon 5.7. Noen problemer ligger i det faktum at vi bruker modusen mester mester, når den eksterne masteren er i modus skrivebeskyttet. Det vil si at kamptrafikken går til ett datasenter, og det andre er et sikkerhetskopi.

Topologien ser slik ut:

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Oppdateringen må starte med replikaer mysql replica dc 2, mysql master dc 2 и mysql replica dc 1, og avslutter med mysql master dc 1-serveren. For å være mer pålitelig stoppet vi de virtuelle maskinene, tok øyeblikksbilder av dem, og rett før oppdateringen stoppet replikering med kommandoen STOP SLAVE. Resten av oppdateringen ser slik ut:

  1. Vi starter hver replika på nytt ved å legge til 3 alternativer til konfigurasjonene: skip-networking, skip-slave-start, skip-log-bin. Faktum er at oppdatering av databasen genererer binære logger med oppdateringer til systemtabeller. Disse direktivene garanterer at det ikke vil være endringer i applikasjonsdata i databasen, og informasjon om oppdatering av systemtabeller vil ikke bli inkludert i de binære loggene. Dette vil unngå problemer når du gjenopptar replikering.
  2. Installerer pakken percona-server-server. Det er viktig å merke seg at i MySQL versjon 8 no du må kjøre kommandoen mysqlupgrade etter serveroppdatering.
  3. Etter en vellykket start starter vi serveren på nytt - uten parameterne som ble lagt til i første avsnitt.
  4. Vi sørger for at replikering fungerer vellykket: sjekk SHOW SLAVE STATUS og se at tabellene med tellere i applikasjonsdatabasen er oppdatert.

Det hele ser ganske enkelt ut: utvikleroppdateringen var vellykket. Ok, du kan trygt planlegge en nattlig oppdatering for produksjon.

Det var ingen tristhet - vi oppdaterte prod

Overføringen av vellykket dev-erfaring til produksjon var imidlertid ikke uten overraskelser.

Heldigvis begynner selve oppdateringsprosessen med replikaer, så da vi fikk problemer, stoppet vi arbeidet og gjenopprettet replikaen fra øyeblikksbildet. Etterforskningen av problemene ble utsatt til neste morgen. Loggene inneholdt følgende oppføringer:

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

Å undersøke arkivene til ulike e-postlister på Google førte til forståelsen av at dette problemet oppstår pga. MySQL-feil. Selv om dette mer sannsynlig er en verktøyfeil mysqlcheck и mysqlsh.

Det viser seg at MySQL endret måten de representerer data for desimalfelt (int, tinyint, etc.), så mysql-server bruker en annen måte å lagre dem på. Hvis databasen din i utgangspunktet var i versjon 5.5 eller 5.1, og så oppdaterte du til 5.7, så må du kanskje gjøre OPTIMIZE for noen bord. Deretter vil MySQL oppdatere datafilene og overføre dem til gjeldende lagringsformat.

Du kan også sjekke dette med verktøyet 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',
...

Hvis field_type Hvis du har den lik 0, brukes den gamle typen i tabellen - du må utføre OPTIMIZE. Men hvis verdien er 246, har du allerede en ny type. Mer informasjon om typene finner du i kode.

Dessuten, i denne feilen Vi vurderer den andre mulige årsaken, som omgikk oss: fraværet av InnoDB-tabeller i systemtabellen INNODB_SYS_TABLESPACES, hvis de, tabeller, ble opprettet i versjon 5.1. For å unngå problemer ved oppdatering kan du bruke vedlagt SQL-skript.

Hvorfor hadde vi ikke slike problemer på dev? Databasen blir periodisk kopiert dit fra produksjon - dermed tabeller gjenskapes.

Dessverre, på en virkelig fungerende stor database, vil du ikke kunne bare ta og utføre en universal OPTIMIZE. percona-toolkit vil hjelpe her: pt-online-schema-change-verktøyet er utmerket for OPTIMIZE-operasjonen online.

Den oppdaterte planen så slik ut:

  1. Optimaliser alle tabeller.
  2. Oppdater databasene.

For å sjekke det og samtidig finne ut oppdateringstiden, deaktiverte vi en av replikaene og kjørte følgende kommando for alle tabeller:

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

Tabeller oppdateres uten lange låsinger på grunn av at verktøyet oppretter en ny midlertidig tabell som den kopierer data fra hovedtabellen til. I det øyeblikket begge bordene er identiske, er det originale bordet låst og erstattet med det nye. I vårt tilfelle viste en testkjøring at det ville ta omtrent en dag å oppdatere alle tabeller, men kopiering av data førte til for mye belastning på diskene.

For å unngå dette la vi i produksjonen argumentet til kommandoen --sleep med en verdi på 10 - denne parameteren justerer ventelengden etter overføring av en batch med data til en ny tabell. På denne måten kan du redusere belastningen dersom selve applikasjonen som kjører er krevende på responstid.

Etter å ha utført optimaliseringen var oppdateringen vellykket.

... men ikke helt!

Innen en halvtime etter oppdateringen kom klienten med et problem. Databasen fungerte veldig merkelig: med jevne mellomrom startet de tilkoblingen tilbakestilles. Slik så det ut i overvåking:

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

Skjermbildet viser en sagtanngraf på grunn av at noen av MySQL-servertrådene med jevne mellomrom krasjet med en feil. Feil dukket opp i applikasjonen:

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

En rask inspeksjon av loggene viste at mysqld-demonen ikke kunne hente de nødvendige ressursene fra operativsystemet. Mens vi sorterte ut feil, oppdaget vi i systemet "foreldreløse" apparmor-policyfiler:

# 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

Disse filene ble opprettet ved oppgradering til MySQL 5.7 for et par år siden og tilhører en fjernet pakke. Å slette filene og starte apparmor-tjenesten på nytt løste problemet:

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

i konklusjonen

Enhver, selv den enkleste operasjonen, kan føre til uventede problemer. Og selv å ha en gjennomtenkt plan garanterer ikke alltid det forventede resultatet. Nå inkluderer alle oppdateringsplaner vårt team også obligatorisk rensing av unødvendige filer som kan ha dukket opp som et resultat av nylige handlinger.

Og med denne ikke særlig profesjonelle grafiske kreativiteten, vil jeg gjerne si en stor takk til Percona for deres utmerkede produkter!

Oppdaterer MySQL (Percona Server) fra 5.7 til 8.0

PS

Les også på bloggen vår:

Kilde: www.habr.com

Legg til en kommentar