Blog JSystems - uwalniamy wiedzę!

Szukaj

PostgreSQL

Jak zaktualizować klaster PostgreSQL do nowej wersji (pg_upgrade)

W skrócie

  • Chcemy przejść na nowszą główną wersję PostgreSQL (np. z 15 na 17), ale zwykły update pakietu tego nie robi, a zrzut i wczytanie ogromnej bazy trwałyby wiele godzin przestoju.
  • Nowe główne wersje mają niekompatybilny format plików danych, więc katalog starej wersji nie zadziała pod nową - trzeba dane przenieść świadomie, a nie tylko podmienić binaria.
  • Używamy pg_upgrade, który migruje katalog danych do nowego formatu, a w trybie z twardymi dowiązaniami robi to w kilka minut zamiast godzin.

Aktualizacja wersji pobocznej (np. 16.3 na 16.4) to zwykły update pakietu. Ale przejście na nową wersję główną wymaga migracji danych. Pokazujemy, jak zrobić to bezpiecznie i szybko narzędziem pg_upgrade.

Jak to wygląda w praktyce

Nasza wersja PostgreSQL zbliża się do końca wsparcia albo chcemy nowych funkcji z aktualnego wydania. Aktualizujemy pakiet przez menedżer systemu i... baza nie startuje pod nową wersją albo menedżer instaluje nowe binaria obok starych, a klaster wciąż chodzi na poprzedniej wersji. Alternatywa, o której myślimy - pg_dumpall na starej i wczytanie na nowej - przy bazie liczącej setki gigabajtów oznacza wiele godzin przestoju, na który biznes się nie zgodzi. Potrzebujemy sposobu, który przeniesie dane do nowego formatu bez przepisywania każdego wiersza z osobna i zmieści się w krótkim oknie serwisowym.

Dlaczego tak się dzieje

PostgreSQL rozróżnia wersje główne (pierwsza liczba, np. 15, 16, 17) i poboczne (druga część, np. 16.4). Wydania poboczne to tylko poprawki błędów i bezpieczeństwa - zachowują ten sam format plików na dysku, więc aktualizacja to podmiana binariów i restart. Wersje główne wprowadzają zmiany w wewnętrznym układzie katalogu danych i katalogu systemowego, przez co pliki starej wersji są nieczytelne dla nowej. Dlatego nie wystarczy podmienić program - trzeba przekształcić dane. Najprostsze podejście, czyli zrzut logiczny i ponowne wczytanie, jest bezpieczne, ale kosztuje czasem tyle, ile fizyczne przepisanie całej bazy. pg_upgrade obchodzi to sprytnie: zamiast przepisywać dane wierszami, przekształca tylko metadane katalogu systemowego, a właściwe pliki tabel pozostawia na miejscu. W trybie z twardymi dowiązaniami (--link) nie kopiuje nawet plików - tworzy do nich dowiązania w nowym katalogu, więc migracja wielkiej bazy trwa minuty.

Jak to rozwiązać krok po kroku

  1. Robimy pełny backup przed wszystkim. Świeży pg_basebackup lub sprawdzony pg_dumpall - to nasza droga powrotu, gdyby coś poszło nie tak. Bez tego nie zaczynamy.
  2. Instalujemy nową wersję PostgreSQL obok starej (oba zestawy binariów muszą istnieć jednocześnie) i inicjujemy dla niej nowy, pusty katalog danych: initdb -D /var/lib/postgresql/17/data z takim samym kodowaniem i lokalizacją jak stary klaster.
  3. Zatrzymujemy oba klastry - stary i nowy. pg_upgrade wymaga, by żaden z nich nie działał w trakcie migracji.
  4. Uruchamiamy sprawdzenie zgodności bez ruszania danych: pg_upgrade --check z podaniem katalogów danych (-d stary, -D nowy) i katalogów binariów (-b stary, -B nowy). Tryb --check tylko weryfikuje i wskazuje przeszkody (np. niekompatybilne rozszerzenia), niczego nie zmienia.
  5. Gdy sprawdzenie przejdzie czysto, uruchamiamy właściwą migrację tym samym poleceniem bez --check, dodając --link dla trybu z twardymi dowiązaniami (szybki, ale wtedy stary klaster staje się bezużyteczny po starcie nowego - dlatego backup jest obowiązkowy). Bez --link pliki są kopiowane, co jest wolniejsze, lecz zostawia stary klaster nietknięty.
  6. Po zakończeniu migracji przenosimy ustawienia z postgresql.conf i pg_hba.conf starego klastra do nowego (pg_upgrade nie kopiuje konfiguracji) i startujemy nowy klaster.
  7. Uruchamiamy wygenerowany przez pg_upgrade skrypt do odświeżenia statystyk (w nowszych wersjach jest to zalecenie wykonania ANALYZE, np. przez vacuumdb --all --analyze-in-stages) - bez świeżych statystyk planer działa źle zaraz po migracji.

Jak sprawdzić, że zadziałało

Najpierw potwierdzamy wersję: SELECT version(); po połączeniu z nowym klastrem powinno pokazać docelową wersję główną. Sprawdzamy, że klaster wstał czysto i że wszystkie bazy oraz role są na miejscu (\l i \du w psql). Robimy kilka reprezentatywnych zapytań aplikacyjnych i, jeśli mamy testy, przepuszczamy je przez nową bazę. Kontrolujemy log startowy pod kątem ostrzeżeń o rozszerzeniach - część z nich (np. własne rozszerzenia) trzeba czasem doinstalować w nowej wersji i wykonać ALTER EXTENSION ... UPDATE. Jeśli używaliśmy trybu --link, pg_upgrade zostawia skrypt delete_old_cluster - uruchamiamy go dopiero wtedy, gdy jesteśmy pewni, że nowy klaster działa poprawnie, bo to on kasuje stare dane. Do tego czasu trzymamy zarówno stary katalog, jak i backup.

Wróć do listy: 100 najczęstszych pytań i problemów z PostgreSQL

Szkolenie Administracja, replikacja i tuning baz danych PostgreSQL

Sprawdź szkolenie: Administracja, replikacja i tuning baz danych PostgreSQL

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Szkolenie Zaawansowana administracja PostgreSQL - HA, DR, monitoring, skalowanie

Sprawdź szkolenie: Zaawansowana administracja PostgreSQL (HA, DR, monitoring, skalowanie)

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Najczęściej zadawane pytania

Czym różni się aktualizacja wersji pobocznej od głównej?
Wersja poboczna, na przykład z 16.3 na 16.4, to tylko poprawki błędów i bezpieczeństwa przy tym samym formacie plików, więc wystarczy podmienić binaria i zrestartować. Wersja główna, na przykład z 15 na 17, zmienia wewnętrzny układ katalogu danych, przez co pliki starej wersji są nieczytelne dla nowej i trzeba przeprowadzić migrację narzędziem pg_upgrade.
Dlaczego pg_upgrade jest szybszy niż zrzut i wczytanie bazy?
Bo nie przepisuje danych wierszami. pg_upgrade przekształca tylko metadane katalogu systemowego, a właściwe pliki tabel zostawia na miejscu. W trybie z twardymi dowiązaniami, flaga --link, nie kopiuje nawet plików, lecz tworzy do nich dowiązania w nowym katalogu, dzięki czemu migracja wielkiej bazy trwa minuty zamiast godzin.
Czy pg_upgrade można uruchomić na wszelki wypadek bez ruszania danych?
Tak. Tryb pg_upgrade --check tylko weryfikuje zgodność starego i nowego klastra i wskazuje przeszkody, na przykład niekompatybilne rozszerzenia, ale niczego nie zmienia. Uruchom go najpierw i dopiero po czystym wyniku wykonaj właściwą migrację tym samym poleceniem bez --check. Oba klastry muszą być zatrzymane.
Co trzeba zrobić po migracji, zanim uznam ją za zakończoną?
Przenieś ustawienia z postgresql.conf i pg_hba.conf, bo pg_upgrade ich nie kopiuje, wystartuj nowy klaster i odśwież statystyki, na przykład przez vacuumdb --all --analyze-in-stages, bo bez nich planer działa źle. Potwierdź wersję przez SELECT version(), sprawdź bazy i role, a stare dane skasuj skryptem delete_old_cluster dopiero, gdy masz pewność, że nowy klaster działa.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...