I de sidste par måneder har jeg arbejdet på online opgradering til meget store databaser som en del af AXLE-projektet, og jeg vil gerne dele mine tanker om emnet, og hvilke fremskridt vi har gjort for nylig.
Før jeg sluttede mig til 2ndQuadrant, arbejdede jeg i Skype, hvor virksomheden ikke tillod et vedligeholdelsesvindue for vores databaser. Dette betød, at der ikke var tilladt nedetid til implementeringer, opgraderinger osv. Den slags regler får dig til at ændre måden, du gør tingene på. De fleste ændringer er små, du laver ingen tunge låse, du har replikaer for at give mulighed for hurtig fail-over. Men selvom du kan gøre dine udgivelser små og ikke-blokerende, hvad sker der, når du skal lave en større versionsopgradering af PostgreSQL-databasen?
Du kan være i en anden situation, da de fleste virksomheder har et opgraderingsvindue, og du kan derfor have råd til noget nedetid under opgraderingen. Dette medfører dog to problemer. For det første kan ingen virksomheder faktisk lide nedetiderne, selvom de er tilladt. Og endnu vigtigere, når først din database vokser ud over gigabyte i størrelse til rækken af terabyte eller hundredvis af terabyte, kan nedetiden tage dage eller endda uger, og ingen har råd til at stoppe deres operationer i så lang tid. Resultatet er, at mange virksomheder ofte springer vigtige opgraderinger over, hvilket gør den næste faktisk endnu mere smertefuld. Og udviklerne mangler nye funktioner, præstationsforbedringer. De (virksomhederne) risikerer til tider endda at køre en PostgreSQL-version, der ikke længere understøttes og har kendte datakorruption eller sikkerhedsproblemer. I de følgende afsnit vil jeg fortælle lidt om mit arbejde med at gøre opgraderingerne mindre tidskrævende og dermed mindre smertefulde og forhåbentlig hyppigere.
Lad mig starte med en lille historie først. Før PostgreSQL 9.0 var den eneste måde at lave en større versionsopgradering på at køre pg_dump og gendanne dumpet til en instans, der kører en nyere version af PostgreSQL. Denne metode krævede, at strukturen og alle data blev læst fra databasen og skrevet ind i en fil. Læs derefter fra filen og indsat i en ny database, indekser skal genopbygges osv.
Som du kan forestille dig, kan denne proces tage ret lang tid. Forbedringer i ydeevnen blev foretaget i 8.4 for pg_restore med -j-indstillingen tilføjet, hvor du kunne angive, hvor mange parallelle job, der skal køres. Dette gør det muligt at gendanne flere tabeller (indekser osv.) parallelt, hvilket gør gendannelsesprocessen hurtigere for brugerdefinerede formatdumps. 9.3-versionen tilføjede en lignende mulighed til pg_dump, hvilket forbedrede ydeevnen yderligere. Men i betragtning af hvor hurtigt datamængderne vokser, er paralleliseringen i sig selv ikke nok til at give nogen seriøs gevinst i den tid, der kræves til opgradering.
Så i PostgreSQL 9.0 ankom et hjælpeprogram kaldet pg_upgrade. Pg_upgrade dumper kun strukturerne og gendanner dem i den nye klynge. Men det kopierer datafilerne, som de er på disken, hvilket er meget hurtigere end at dumpe dem i logisk format og derefter genindsætte. Dette er godt nok for små databaser, fordi det betyder en nedetid i et område på minutter eller timer, en tid, der er acceptabel for mange scenarier. Der er også link-tilstanden, som bare opretter hårde links (forbindelsespunkter på Windows), som gør denne proces endnu hurtigere. Men fra mit personlige synspunkt er det for farligt at køre en sådan opsætning på en produktionsmasterserver. Jeg vil kort forklare hvorfor. Hvis noget går galt, når du først starter din nye server, der blev opgraderet ved hjælp af link-tilstanden, står du pludselig uden produktionsdatabase og skal fail-over, eller endnu værre, du skal gendanne fra backup. Det betyder, at du ikke kun undlod at opgradere, men at du bare forårsagede yderligere nedetid! Held og lykke med at få godkendelse næste gang.
Nu bruger mange mennesker, der ikke har råd til lange nedetider for opgraderinger, de triggerbaserede replikeringsløsninger som Slony eller Londiste til at udføre opgraderingen. Dette er en god løsning, fordi du kan replikere dine data, mens den originale server kører, og derefter skifte med minimal nedetid. I praksis er der dog flere problemer. En af dem er, at de triggerbaserede løsninger ofte er klodsede at konfigurere, især hvis du kun gør det en gang hvert par år og kun for at lave opgraderingen. Det er også nemt at gå glip af et bord eller tilføje tabeller i forkert rækkefølge og dermed ikke få det fulde eksemplar. Jeg har set dette i praksis, og folk, der udfører opgraderingen, arbejdede med den triggerbaserede replikering på daglig basis . Et andet problem er, at de triggerbaserede løsninger tilføjer en betydelig belastning på kildedatabasen, hvilket nogle gange gør opgraderingen umulig på grund af, at databaseserveren bliver overbelastet, når replikeringen er aktiveret. Og sidst, men ofte ikke mindst, kan det tage meget lang tid, før den triggerbaserede replikering rent faktisk flytter dataene til den nye server. Ved sidste gang jeg var involveret i et opgraderingsprojekt, tog den triggerbaserede løsning omkring en måned at kopiere databasen og indhente ændringer. Ja, en måned.
Med PostgreSQL 9.4 kommer den logiske afkodningsfunktion, som giver en frisk start til at designe en ny og bedre online opgraderingsproblemløsning. Det, vi gjorde, som en del af AXLE-projektet, var at skabe et værktøj, som kombinerer den logiske afkodning med de ovenfor beskrevne teknikker. Løsningen løser de fleste problemer med tidligere tilgange. Uni-Directional Replication PostgreSQL-udvidelsen (forkortet UDR) udfører logisk replikering ved hjælp af logisk afkodning af WAL-loggen (Write Ahead). Takket være dette er påvirkningen på masterserveren næsten på niveau med den fysiske streaming-replikering, så den ekstra belastning forårsaget af igangværende opgradering er minimal på det kørende system. Det giver også værktøjer til at initialisere nye noder, både ved hjælp af fysisk og logisk backup. Du kan endda slå eksisterende fysisk standby til UDR standby. Og fordi det er et logisk replikeringssystem, er det muligt at designe det på en måde, der understøtter replikering på tværs af versioner.
Hvad alt dette betyder er, at vi nu kan bruge UDR i kombination med pg_upgrade til at lave en online opgradering af større PostgreSQL-version med minimal nedetid, på kort tid og med minimal indvirkning på det kørende system.
Et eksempel på, hvordan dette kan se ud i praksis:
- Gør pg_basebackup af eksisterende instans.
- Konfigurer UDR-replikeringen mellem den oprindelige instans og den, der er oprettet af basebackup.
- Pg_opgrader den nye instans.
- Lad UDR afspille de ændringer, der skete i mellemtiden.
- Skift trafikken til den nye forekomst.
Se UDR Online-opgraderingsvejledningen på PostgreSQL-wikien for hvordan du gør det med mere detaljerede instruktioner. UDR-kilderne er tilgængelige i 2ndquadrant_bdr-lageret på PostgreSQL git-serveren (bdr-plugin/next branch).
Endelig, da UDR ikke kun er et online opgraderingsværktøj, men også en replikeringsløsning, kan det bruges til dine normale replikeringsbehov i stedet for den fysiske streaming-replikering. Ydermere giver det adskillige fordele, såsom muligheden for at oprette midlertidige tabeller, replikere fra flere OLTP-databaser til én big data warehouse-database eller replikere kun en del af databasen.
Mit håb er, at denne indsats vil betyde, at nedetidsovervejelser ikke længere er et problem, når det kommer til at opgradere fra PostgreSQL 9.4 og nyere til en ny større version.
Den forskning, der fører til disse resultater, har modtaget støtte fra EU's syvende rammeprogram (FP7/2007-2013) under tilskudsaftale nr. 318633.