sql >> Databasteknik >  >> RDS >> PostgreSQL

Uppgradera din databas till PostgreSQL version 10 - Vad du bör veta

Eftersom fler och fler inlägg om PostgreSQL 11 dyker upp på webben, desto mer föråldrad kan du känna dig när du använder Postgres 9. Även om versionen av PostgreSQL 10 släpptes för bara några månader sedan, pratar folk redan om nästa version. Saker och ting rör på sig, så du vill inte bli kvar. I den här bloggen kommer vi att diskutera vad du behöver veta för att uppgradera till den senaste versionen, Postgres 10.

Uppgraderingsalternativ

Det första du bör vara medveten om innan du börjar är att det finns flera sätt att göra uppgraderingen på:

  1. Traditionell pg_dumpall(pg_dump) / pg_restore(psql)
  2. Traditionell pg_upgrade
  3. Triggerbaserad replikering (Slony, självskriven)
  4. Använda pglogisk replikering

Varför finns det en sådan variation? Eftersom var och en har en annan historia, kräver olika insatser för att skapas och erbjuda olika tjänster. Låt oss titta närmare på var och en av dem.

Traditionell dumpning/återställning

pg_dump t > /tmp/f
psql -p 5433 -f /tmp/f

Traditionell dumpning/återställning tar längst tid att slutföra och ändå är det ofta ett populärt val för dem som har råd med stilleståndstiden. För det första är det lika enkelt som att ta en logisk säkerhetskopia och återställa den till en ny, högre version av databasen. Man kan säga att det inte är en uppgradering, egentligen, eftersom du "importerar" dina data till en "ny struktur". Som ett resultat kommer du att sluta med två inställningar - en gammal (lägre version) och den nyligen uppgraderade. Om återställningsprocessen slutförs utan fel är du i stort sett där. Om inte, måste du modifiera det befintliga gamla klustret för att eliminera eventuella fel och starta processen igen.

Om du använder psql för import kan du också behöva skapa några förinstallerade skript själv för att köra på den nya installationen innan migreringen. Till exempel skulle du vilja pg_dumpall -g för att få en lista över nödvändiga roller att förbereda i den nya installationen, eller tvärtom kör pg_dump -x för att hoppa över behörigheter från den gamla. Denna process är ganska enkel på små databaser, komplexiteten växer med storleken och komplexiteten på din db-struktur och beror på vilka funktioner du har konfigurerat. I grund och botten för att den här metoden ska bli framgångsrik måste du fortsätta försöka och fixa tills uppgraderingen lyckas.

Fördelarna med att använda denna metod inkluderar...

  • Även om du kan spendera lång tid med en säkerhetskopia du har gjort - belastningen på den gamla servern är lika liten som att ta en säkerhetskopia.
  • Denna metod är för det mesta bara en backup-återställningssekvens (potentiellt med vissa trollformler, låtar och trumspel)
  • Att använda den här metoden är det äldsta sättet att uppgradera och har verifierats av MÅNGA personer

När du äntligen har slutfört uppgraderingen måste du antingen stänga av den gamla servern eller acceptera viss dataförlust (eller alternativt spela upp DML som hände på den gamla servern medan du återställde en säkerhetskopia till den nya servern). Och tiden som ägnas åt att göra det är i förhållande till storleken på din databas.

Du kan naturligtvis börja "använda" en ny databas innan återställningen är klar (särskilt innan alla index är byggda - ofta är den mest tid det tar för index). Men inte desto mindre är sådana stillestånd ofta oacceptabelt.

Traditionell pg_upgrade

MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/initdb -D tl0 >/tmp/suppressing_to_save_screen_space_read_it

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/pg_upgrade -b /usr/local/Cellar/postgresql/9.5.3/bin -B /usr/local/Cellar/postgresql/10.2/bin -d t -D tl0 | tail
Creating script to delete old cluster                        ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    ./analyze_new_cluster.sh

Running this script will delete the old cluster’s data files:
    ./delete_old_cluster.sh

Traditionell pg_upgrade skapades för att förkorta tiden det tar att uppgradera till en större version. Beroende på mängden relationer du har kan det vara så snabbt som minuter (sekunder i löjliga fall, som en tabelldatabas och timmar i "motsatta fall"), speciellt med --link argument.

Förberedelsesekvensen skiljer sig något från den första uppgraderingsmetoden. För att håna uppgraderingen och därmed kontrollera om det är möjligt, bör du bygga strömmande replikering eller återställa en standby-server från WALs. Varför är detta så komplicerat? Du vill vara säker på att testa uppgraderingen på en så nära-i-state-databas som du hade från början. "Binär" replikering eller PITR kommer att hjälpa oss här. När du är klar med återställningen och recovery_target_action =promote (PITR) eller främjat den nybyggda slaven (pg_ctl promote eller placera en triggerfil) (strömmande replikering) kan du sedan försöka köra pg_upgrade. Om du kontrollerar pg_upgrade_internal.log får du en uppfattning om processen lyckades eller inte. Dessutom har du samma försök-och-fix-metod som den tidigare metoden. Du sparar de åtgärder som vidtagits mot testdatabasen i ett skript tills du lyckas pg_upgrade den. Dessutom kan du förstöra test som inte längre behövs uppgraderad databas, kör sedan sparat skript för att förbereda den ursprungliga databasen för att utföra uppgraderingen.

Fördelarna med att använda denna metod inkluderar...

  • Kortare driftstopp än logisk säkerhetskopiering/återställning
  • En snygg process - pg_upgrade uppgraderar den ursprungliga databasen med befintliga data och struktur
  • Har använts mycket tidigare och skulle fortfarande föredras för de flesta DBA:er som kör versioner under 9.4 (vilket tillåter användning av pglogical)

Nackdelarna med att använda denna metod inkluderar...

  • Kräver driftstopp

Triggerbaserad replikering

Förutsatt att version 10 är på port 5433 och har samma tabell förberedd:

db=# create server upgrade_to_10 foreign data wrapper postgres_fdw options (port '5433', dbname 'dbl0');
CREATE SERVER
Time: 9.135 ms
db=# create user mapping for vao SERVER upgrade_to_10 options (user 'vao');
CREATE USER MAPPING
Time: 8.741 ms
db=# create foreign table rl0 (pk int, t text) server upgrade_to_10 options (table_name 'r');
CREATE FOREIGN TABLE
Time: 9.358 ms

Detta är en extremt förenklad fn() och trigger för mycket grundläggande logisk replikering. Ett sådant tillvägagångssätt är så primitivt att det inte fungerar med främmande nycklar, men koden är kort:

db=# create or replace function tf() returns trigger as $$
begin
 if TG_0P = 'INSERT' then
   insert into r10 select NEW.*;
 elseif TG_0P = 'UPDATE' then
   delete from rl0 where pk = NEW.pk;
   insert into rl0 select NEW.*;
 elseif TG_0P = 'DELETE' then
   delete from rl0 where pk = OLD.pk;
 end if;
return case when TG_0P in ('INSERT','UPDATE') then NEW else OLD end;
end;
SS language plpgsql;
CREATE FUNCTION
Time: 8.531 ms
db=# create trigger t before insert or update or delete on r for each row execute procedure tf(); CREATE TRIGGER
Time: 8.813 ms

Exempel:

db=# insert into r(t) select chr(g) from generate_series(70,75) g;
INSERT 0 6
Time: 12.621 ms
db=# update r set t = 'updated' where pk=2;
UPDATE 1
Time: 10.398 ms
db=# delete from r where pk=1;
DELETE 1
Time: 9.634 ms
db=# select * from r;
 pk |    t
----+---------
  3 | H
  4 | I
  5 | J
  6 | K
  2 | updated
(5 rows)

Time: 9.026 ms
db=# select * from rl0;
 pk |    t
----+---------
  3 | H
  4 | I
  5 | J
  6 | K
  2 | updated
(5 rows)

Time: 1.201 ms

Slutligen, kontrollera att vi replikerar till en annan databas:

db=# select *,current_setting('port') from dblink('upgrade.to.lO','select setting from pg_settings where name=$$port$$') as t(setting_10 text);
 setting_10 | currerrt.setting
------------+------------------
 5433       | 5432
(l row)

Time: 23.633 ms

Jag skulle kalla denna metod den mest exotiska. Både för det faktum att med strömmande replikering och senare med pglogical blir användningen av triggerbaserad replikering mindre populär. Den har en högre belastning på mastern, ökad komplexitet under installationen och en brist på välstrukturerad dokumentation. Det finns ingen förberedelse (som sådan) av processen här, eftersom du bara vill ställa in Slony på olika större versioner.

Fördelarna med att använda denna metod inkluderar...

  • Inga säkerhetskopior behöver tas och ingen stilleståndstid krävs (särskilt du står bakom någon pgbouncer eller haproxy).

Nackdelarna med att använda denna metod inkluderar...

  • Hög komplexitet i installationen
  • Brist på strukturerad dokumentation
  • Inte särskilt populärt – färre användarfall att studera (och dela)

På samma sätt är självskriven triggerreplikering ett annat möjligt sätt att uppgradera. Även om idén är densamma (du skapar en ny databas med högre versioner och ställer in triggers på lägre version för att skicka modifierad data till den), kommer den självskrivna inställningen att vara tydlig för dig. Du kommer inte att ha något behov av support och därmed potentiellt använda mindre resurser när du kör det. Naturligtvis, av samma anledning kommer du förmodligen att sluta med att vissa funktioner saknas eller inte fungerar som förväntat. Om du har flera tabeller att flytta till nya versioner, kommer ett sådant alternativ förmodligen att ta dig mindre tid och, om det görs bra, kan det vara mindre resurskrävande. Som en bonus kan du kombinera några ETL-transformationer med uppgraderingen och byta över till en ny version utan stillestånd.

Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

Logisk replikering med pglogical

Detta är ett mycket lovande nytt sätt att uppgradera Postgres. Tanken är att sätta upp logisk replikering mellan olika större versioner och bokstavligen ha en parallell, högre (eller lägre) versionsdatabas som kör samma data. När du är redo byter du bara anslutningar med din applikation från gammal till ny.

Fördelarna med att använda denna metod inkluderar...

  • I princip ingen stilleståndstid
  • Extremt lovande funktion, mycket mindre ansträngning än triggerbaserad replikering

Nackdelarna med att använda denna metod inkluderar...

  • Fortfarande mycket komplicerad att installera (särskilt för äldre versioner)
  • Brist på strukturerad dokumentation
  • Inte särskilt populärt – färre användarfall att studera (och dela)

Både de triggerbaserade och pglogical replikeringens huvudversionsmigrering kan användas för att nedgradera versionen (upp till ett rimligt värde förstås, t.ex. är pglogical endast tillgänglig från 9.4 och triggerreplikering blir svårare och svårare att ställa in som den version du vill ha att nedgradera till blir äldre).

Åtgärder som ska vidtas före uppgraderingen

  • Ta en säkerhetskopia
  • Se till att det finns tillräckligt med diskutrymme
  • Kontrollera dina tillägg (viktigt att alla externa moduler också är binärkompatibla, även om detta inte kan kontrolleras av pg_upgrade)
  • Se till att använda samma datcollate och datctype och så vidare (kontrollera pg_database) på ny databas
  • Kontrollera (DDL + Drop) vyer, funktioner, tillägg, typer som kan bryta uppgraderingen
  • Använd --check före verkligen pg_upgrade

Åtgärder som ska vidtas efter uppgraderingen

  • Konsultera pg_upgrade_server.log (om du använde pg_upgrade)
  • Kör analys på uppgraderade databaser (valfritt, eftersom det skulle göras med autovakuum, men du kan välja vilka relationer som ska analyseras först om du gör det själv)
  • Förvärm populära sidor (valfritt, men kan öka prestandan i början)

Slutsats

Här är några allmänna anteckningar som är bra att känna till innan du bestämmer dig för att gå till PostgreSQL version 10...

  • pg_sequences introducerades, vilket ändrade beteendet hos tidigare populära SELECT * FROM sequence_name - nu bara last_value | log_cnt | is_called returneras, gömmer sig från dina "initialegenskaper" (justera eventuell kod som förlitar sig på ändrat beteende)
  • pg_basebackup strömmar WAL som standard. Efter uppgraderingen kan du behöva ändra dina skript (alternativ -x har tagits bort)
  • Alla pg_ctl-åtgärder väntar på slutförande. Tidigare var du tvungen att lägga till -w för att undvika att försöka ansluta till databasen direkt efter start av pg_ctl. Så om du fortfarande vill använda "async" start eller stop, måste du uttryckligen markera det med -W. Du kan behöva justera dina skript så att de beter sig som avsett.
  • Alla skript för arkivering av WALs eller övervakning/kontroll av strömmande replikering eller PITR måste granskas för att justera dem till ändrade xlog-namn. T.ex. select * from pg_is_xlog_replay_paused() kommer inte längre att visa dig statusen för slav-WALs replay - du måste använda select * from pg_is_wal_replay_paused() istället. Även cp /blah/pg_xlog/* måste ändras till /blah/pg_wal/* och så vidare i princip för alla förekomster av pg_xlog. Anledningen bakom en sådan massiv, icke bakåtkompatibel förändring är att ta itu med fallet när en nybörjare tar bort skriv-ahead-loggar för att "rensa lite utrymme" genom att ta bort loggar och förlorar databasen.
  • Justera skript med hjälp av pg_stat_replication för nya namn (plats ändrad till lsn)
  • Justera frågor med inställda returnerande funktioner om det behövs
  • Om du använde pglogical som tillägg före version 10, kan du behöva justera pg_hba.confs ändrade värde mellan "kolumner"
  • Justera skript för ett nytt namn på pg_log som är log, så något som hitta /pg_data/pg_log/postgresql-*  -mmin +$(((60*48)) -typ f -exec bash /blah/moveto.s3 .sh {} \; skulle jobba. Naturligtvis kan du skapa en symbolisk länk istället, men åtgärder skulle behöva vidtas för att hitta loggar på standardplatsen. En annan liten ändring av standardvärdena är log_line_prefix - om ditt reguljära uttryck berodde på ett visst format måste du justera det.
  • Om du fortfarande använde okrypterade lösenord i dina Postgres-databaser tar den här versionen bort det. Så det är dags att reda ut saker för dem som litade på --okrypterat...
  • Resten av de inkompatibla ändringarna med tidigare utgåvor är antingen för färska för att kunna refereras till i massor av kod (min_parallel_relation_size) eller för gamla (extern tsearch2) eller är för exotiska (borttagning av flyttalstidsstämplar stöds i build), så vi kommer att skippa dem. Naturligtvis finns de listade på releasesidan.
  • Som det var med 9.5 till 9.6 kan du behöva justera dina skript för att fråga pg_stat_activity (en ny kolumn och nya möjliga värden)
  • Om du sparade/analyserade vacuum verbose output, kan du behöva justera din kod
  • Du kanske också vill ta en titt på den nya partitioneringsimplementeringen - du kanske vill ändra din befintliga "uppsättning" för att följa nya "standarder"
  • kontrollera tidslinjen (återställs för den nya databasen om du pg_upgrade)

Förutom dessa steg som du måste känna till för att uppgradera till 10, finns det massor av saker som gör den här utgåvan till en efterlängtad sådan. Vänligen läs avsnittet om ändringar i release notes eller depesz bloggen.


  1. Hur man behandlar MAX() i en tom tabell som 0 istället för NULL

  2. Kan jag lägga till en UNIK begränsning till en PostgreSQL-tabell efter att den redan har skapats?

  3. Felsökning av MySQL-replikering:Del ett

  4. SQL Server AlwaysOn Availability Groups:Installation och konfiguration, del 1