Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Framstegen står inte stilla, så anledningarna till att uppgradera till de senaste versionerna av MySQL blir allt mer övertygande. För inte så länge sedan, i ett av våra projekt, var det dags att uppdatera de mysiga Percona Server 5.7-klustren till version 8. Allt detta hände på Ubuntu Linux 16.04-plattformen. Hur man utför en sådan operation med minimal stilleståndstid och vilka problem vi stötte på under uppdateringen - läs i den här artikeln.

Utbildning

Alla uppdateringar av databasservern är troligen förknippade med omkonfigurering av databasen: ändringar i kraven på begränsningar av systemresurser och korrigering av databaskonfigurationer som måste rensas från föråldrade direktiv.

Innan vi uppdaterar kommer vi definitivt att hänvisa till den officiella dokumentationen:

Och låt oss göra upp en handlingsplan:

  1. Korrigera konfigurationsfiler genom att ta bort föråldrade direktiv.
  2. Kontrollera kompatibilitet med verktyg.
  3. Uppdatera slavdatabaser genom att installera paketet percona-server-server.
  4. Uppdatera mastern med samma paket.

Låt oss titta på varje punkt i planen och se vad som kan gå fel.

VIKTIGT! Proceduren för att uppdatera ett MySQL-kluster baserat på Galera har sina egna finesser som inte beskrivs i artikeln. Du bör inte använda denna instruktion i detta fall.

Del 1: Kontrollera konfigurationer

MySQL togs bort i version 8 query_cache. Det var han faktiskt förklarats föråldrad tillbaka i version 5.7, men nu helt raderad. Följaktligen är det nödvändigt att ta bort de tillhörande direktiven. Och för att cache-förfrågningar kan du nu använda externa verktyg - t.ex. ProxySQL.

Även i konfigurationen fanns föråldrade direktiv om innodb_file_format. Om det i MySQL 5.7 var möjligt att välja InnoDB-formatet, fungerar den 8:e versionen redan endast med Barracuda-format.

Vårt resultat är att följande direktiv tas bort:

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

För att kontrollera kommer vi att använda Docker-bilden av Percona Server. Vi kommer att placera serverkonfigurationen i katalogen mysql_config_test, och bredvid den kommer vi att skapa kataloger för data och loggar. Exempel på Percona-serverkonfigurationstest:

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

Nedersta raden: antingen i Docker-loggarna eller i katalogen med loggarna - beroende på dina inställningar - kommer en fil att dyka upp där de problematiska direktiven kommer att beskrivas.

Här är vad vi hade:

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.

Därför behövde vi fortfarande ta reda på kodningarna och ersätta det föråldrade direktivet expire-logs-days.

Del 2: Kontroll av fungerande installationer

Uppdateringsdokumentationen innehåller 2 verktyg för att kontrollera databasen för kompatibilitet. Deras användning hjälper administratören att kontrollera kompatibiliteten hos den befintliga datastrukturen.

Låt oss börja med det klassiska mysqlcheck-verktyget. Kör helt enkelt:

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

Om inga problem hittas kommer verktyget att avslutas med kod 0:

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Dessutom finns ett verktyg tillgängligt i moderna versioner av MySQL mysql-skal (i fallet med Percona är detta paketet percona-mysql-shell). Det är en ersättning för den klassiska mysql-klienten och kombinerar funktionerna hos en klient, en SQL-kodredigerare och MySQL-administrationsverktyg. För att kontrollera servern innan du uppdaterar kan du köra följande kommandon genom den:

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

Här är kommentarerna vi fick:

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

I allmänhet inget kritiskt - bara varningar om kodningar (se nedan). Totalt resultat:

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Vi beslutade att uppdateringen skulle gå utan problem.

En notering om varningarna ovan som indikerar problem med kodningar. Faktum är att UTF-8 i MySQL tills nyligen var inte "sant" UTF-8, eftersom det bara lagrade 3 byte istället för 4. I MySQL 8 är detta äntligen bestämde sig för att fixa det: alias utf8 kommer snart att leda till kodning utf8mb4, och de gamla kolumnerna i tabellerna kommer att bli utf8mb3. Ytterligare kodning utf8mb3 kommer att tas bort, men inte i den här utgåvan. Därför beslutade vi att korrigera kodningarna redan på den körande DBMS-installationen, efter att ha uppdaterat den.

Del 3: Serveruppdateringar

Vad kan gå fel när det finns en så smart plan? .. Vi förstod mycket väl att nyanser alltid inträffar och genomförde det första experimentet på ett MySQL-dev-kluster.

Som redan nämnts, officiell dokumentation täcker frågan om uppdatering av MySQL-servrar med repliker. Summan av kardemumman är att du först bör uppdatera alla repliker (slavar), eftersom MySQL 8 kan replikera från en masterversion 5.7. Vissa svårigheter ligger i det faktum att vi använder läget mästare <-> mästare, när fjärrmastern är i läge skriv. Det vill säga, i själva verket går stridstrafik till ett datacenter och det andra är en backup.

Topologin ser ut så här:

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Uppdateringen måste börja med repliker mysql replica dc 2, mysql master dc 2 и mysql replica dc 1, och avsluta med mysql master dc 1-servern. För att vara mer pålitlig stoppade vi de virtuella maskinerna, tog ögonblicksbilder av dem och omedelbart innan uppdateringen stoppade replikeringen med kommandot STOP SLAVE. Resten av uppdateringen ser ut så här:

  1. Vi startar om varje replik genom att lägga till tre alternativ till konfigurationerna: skip-networking, skip-slave-start, skip-log-bin. Faktum är att uppdatering av databasen genererar binära loggar med uppdateringar av systemtabeller. Dessa direktiv garanterar att det inte kommer att ske några ändringar av applikationsdata i databasen, och information om uppdatering av systemtabeller kommer inte att inkluderas i de binära loggarna. Detta kommer att undvika problem när du återupptar replikeringen.
  2. Installerar paketet percona-server-server. Det är viktigt att notera att i MySQL version 8 ingen du måste köra kommandot mysqlupgrade efter serveruppdatering.
  3. Efter en lyckad start startar vi om servern igen - utan parametrarna som lades till i första stycket.
  4. Vi ser till att replikeringen fungerar: kontrollera SHOW SLAVE STATUS och se att tabellerna med räknare i applikationsdatabasen är uppdaterade.

Det hela ser ganska enkelt ut: utvecklaruppdateringen lyckades. Ok, du kan säkert schemalägga en nattlig uppdatering för produktion.

Det var ingen sorg - vi uppdaterade proden

Överföringen av framgångsrik utvecklingserfarenhet till produktion var dock inte utan överraskningar.

Lyckligtvis börjar själva uppdateringsprocessen med repliker, så när vi stötte på svårigheter stoppade vi arbetet och återställde repliken från ögonblicksbilden. Utredningen av problemen sköts upp till nästa morgon. Loggarna innehöll följande poster:

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

Att undersöka arkiven för olika e-postlistor på Google ledde till förståelsen att detta problem uppstår p.g.a. MySQL-bugg. Även om det här är mer troligt ett verktygsfel mysqlcheck и mysqlsh.

Det visar sig att MySQL ändrade hur de representerar data för decimalfält (int, tinyint, etc.), så mysql-server använder ett annat sätt att lagra dem. Om din databas initialt var i version 5.5 eller 5.1, och sedan uppdaterade du till 5.7, då kan du behöva göra OPTIMIZE för vissa bord. Sedan kommer MySQL att uppdatera datafilerna och överföra dem till det aktuella lagringsformatet.

Du kan också kontrollera detta med verktyget 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',
...

Om field_type Om du har det lika med 0, används den gamla typen i tabellen - du måste utföra OPTIMIZE. Men om värdet är 246 har du redan en ny typ. Mer information om typerna finns i koda.

Dessutom i denna bugg Vi överväger den andra möjliga orsaken, som förbi oss: frånvaron av InnoDB-tabeller i systemtabellen INNODB_SYS_TABLESPACES, om de, tabeller, skapades i version 5.1. För att undvika problem vid uppdatering kan du använda bifogat SQL-skript.

Varför hade vi inte sådana problem på dev? Databasen kopieras med jämna mellanrum dit från produktionen - alltså, tabeller återskapas.

Tyvärr, på en riktigt fungerande stor databas, kommer du inte att kunna bara ta och köra en universal OPTIMIZE. percona-toolkit kommer att hjälpa till här: verktyget pt-online-schema-change är utmärkt för onlineoperationen OPTIMIZE.

Den uppdaterade planen såg ut så här:

  1. Optimera alla tabeller.
  2. Uppdatera databaserna.

För att kontrollera det och samtidigt ta reda på uppdateringstiden inaktiverade vi en av replikerna och körde följande kommando för alla 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 uppdateras utan långa låsningar på grund av att verktyget skapar en ny temporär tabell som den kopierar data från huvudtabellen till. I det ögonblick då båda borden är identiska, låses det ursprungliga bordet och ersätts med det nya. I vårt fall visade en testkörning att det skulle ta ungefär en dag att uppdatera alla tabeller, men kopiering av data orsakade för mycket belastning på diskarna.

För att undvika detta lade vi i produktionen till argumentet till kommandot --sleep med ett värde på 10 - denna parameter justerar väntelängden efter att ha överfört en batch data till en ny tabell. På så sätt kan du minska belastningen om den faktiska applikationen är krävande på svarstid.

Efter att ha utfört optimeringen lyckades uppdateringen.

... men inte helt!

Inom en halvtimme efter uppdateringen kom klienten med ett problem. Databasen fungerade väldigt konstigt: med jämna mellanrum startade de anslutningen återställs. Så här såg det ut vid övervakning:

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

Skärmdumpen visar en sågtandsgraf på grund av att några av MySQL-servertrådarna periodvis kraschade med ett fel. Fel uppstod i applikationen:

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

En snabb inspektion av loggarna avslöjade att mysqld-demonen inte kunde få de nödvändiga resurserna från operativsystemet. När vi red ut fel upptäckte vi i systemet "föräldralösa" 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

Dessa filer skapades vid uppgradering till MySQL 5.7 för ett par år sedan och tillhör ett borttaget paket. Att ta bort filerna och starta om apparmor-tjänsten 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

Sammanfattningsvis

Alla, även den enklaste operationen, kan leda till oväntade problem. Och även att ha en genomtänkt plan garanterar inte alltid det förväntade resultatet. Nu inkluderar alla uppdateringsplaner som vårt team har också den obligatoriska rengöringen av onödiga filer som kunde ha dykt upp som ett resultat av de senaste åtgärderna.

Och med denna inte särskilt professionella grafiska kreativitet vill jag säga ett stort tack till Percona för deras utmärkta produkter!

Uppdaterar MySQL (Percona Server) från 5.7 till 8.0

PS

Läs även på vår blogg:

Källa: will.com

Lägg en kommentar