PostgreSQL jest systemem/aplikacją zbudowaną w oparciu o standardowy model klient/serwer. W artykule zostanie omówiona architektura PostgreSQL.
Architektura klient-serwer
Architektura PostgreSQL klient-serwer to model obliczeniowy, w którym serwer obsługuje, dostarcza i zarządza większością zasobów i usług żądanych przez klienta. Jest również znany jako sieciowy model obliczeniowy lub sieć klient-serwer, ponieważ wszystkie żądania i usługi są dostarczane przez sieć.
Komponent serwerowy PostgreSQL reprezentują procesy serwera, które zarządzają plikami bazy danych, akceptują połączenia z bazą danych z aplikacji klienckich i wykonują akcje bazy danych w imieniu klientów. Kluczową rolę pełni tutaj Postmaster Daemon Process, który nosi nazwę postgres.
Komponent kliencki to różnego typu aplikacje klienckie, dostarczające najczęściej mechanizmy edycji i prezentacji danych dla użytkowników. Niektóre aplikacje klienckie są dostarczane z dystrybucją PostgreSQL, natomiast większość jest opracowywana przez innych dostawców.
Naturalnie w przypadku aplikacji klient/serwer, klient i serwer mogą (choć nie muszą) znajdować się na różnych hostach. W takim przypadku komunikują się przez połączenie sieciowe TCP/IP.
Serwer PostgreSQL może obsługiwać wiele jednoczesnych połączeń (sesji przychodzących) od klientów. Aby to osiągnąć, rozpoczyna nowy proces dla każdego połączenia. Od tego momentu klient i nowy proces serwera komunikują się bez interwencji oryginalnego procesu postgres. W ten sposób proces serwera głównego zawsze działa, czekając na połączenia klienta, podczas gdy procesy klienta i powiązanego serwera przychodzą i odchodzą.
Gdy użytkownik uruchamia zapytania na PostgreSQL, aplikacja kliencka może łączyć się z serwerem PostgreSQL i przesyłać zapytania za pośrednictwem jednego z wielu interfejsów programistycznych wspieranych przez PostgreSQL, takich jak JDBC, Perl DBD, ODBC itp., co pozwala udostępniać biblioteki po stronie klienta aplikacjom napisanym w różnych technologiach.
W Procesie Klienta komunikacja pomiędzy Aplikacją Klienta a bibliotekami interfejsów programistycznych Klienta odbywa się za pomocą API tychże interfejsów (bibliotek), jak pokazano na poniższym rysunku:
Jak już wyżej wspomniano, centralną rolę w komponencie serwerowym (czyli w serwerze PostgreSQL) pełni Postmaster Daemon Process.
Postmaster Daemon Process
Instancja serwera PostgreSQL jest zarządzana przez proces Postmaster (Postmaster Daemon Process), który jest centralnym procesem koordynującym. Proces ten jest również znany jako proces serwera.
Proces Postmaster jest w rzeczywistości linkiem do polecenia postgres. Link wygląda w następujący sposób:
Proces Postmaster jest odpowiedzialny za:
- Inicjalizację serwera
- Wyłączanie serwera
- Obsługa żądań połączenia od nowych klientów.
- Operacje odzyskiwania
- Uruchamianie procesów w tle (background)
- Uruchamianie procesów zaplecza (backend)
Proces Postmaster jest pierwszym procesem uruchamianym po uruchomieniu PostgreSQL. Podczas uruchamiania wykonuje on odzyskiwanie, inicjuje pamięć współdzieloną i uruchamia procesy w tle. Tworzy również procesy zaplecza, gdy przychodzą żądania połączenia z procesu klienta:
- Kiedy użytkownik nawiązuje połączenie z bazą danych PostgreSQL, musi najpierw nawiązać połączenie z procesem Postmaster. W tym celu proces klienta wyśle wiadomość uwierzytelniającą do głównego procesu Postmastera. Główny proces Postmastera uwierzytelnia się zgodnie z wiadomością.
- Po przejściu weryfikacji główny proces Postmastera rozwidla się (fork).
- Wskazanie na nowy proces Proces obsługi sesji jest dostarczane do obsługi tego połączenia użytkownika. Numer PID procesu usługi sesji możesz wyświetlić za pomocą tabeli pg_stat_activity w następujący sposób:
Jeśli sprawdzimy relacje między procesami za pomocą polecenia pstree, widać że proces Postmaster jest procesem nadrzędnym wszystkich pozostałych procesów serwera.
Jedną z ról procesu Postmaster jest zainicjowanie pamięci współdzielonej.
Pamięć współdzielona
Pamięć współdzielona (shared memory) jest przydzielana przez serwer PostgreSQL po uruchomieniu i jest używany przez wszystkie procesy. Jest to obszar do którego jednocześnie uzyskuje dostęp wiele procesów, aby zapewnić szybkie i wydajne wyniki przy mniejszej nadmiarowości. Shared memory jest przede wszystkim zarezerwowana dla buforowania bazy danych i buforowania dzienników transakcyjnych. W PostgreSQL używane są współdzielone bufory dyskowe i współdzielone tabele. Najważniejszymi elementami w pamięci współdzielonej są bufory Shared Buffer i WAL.
Bufory współdzielone
Odczytywanie lub zapisywanie danych w pamięci jest zawsze szybsze niż na jakimkolwiek innym nośniku. Serwer bazy danych potrzebuje również pamięci do szybkiego dostępu do danych, niezależnie od tego, czy jest to dostęp ODCZYT czy ZAPIS.
Celem buforów dysku współdzielonego jest zminimalizowanie operacji wejścia/wyjścia dysku. Jeśli bufor nie jest używany, wejście/wyjście dysku zajmuje więcej czasu, co powoduje nadmiarowość i nieefektywność systemu. Zalety korzystania ze współdzielonego bufora to:
- Skrócenie czasu dostępu do danych zapisywanych/odczytywanych z dysku
- Łatwiejszy dostęp do bardzo dużej ilości danych.
- Minimalizacja ilości operacji I/O, gdy wielu użytkowników korzysta jednocześnie z systemu.
Rozmiar przestrzeni buforów współdzielonych kontrolowany jest przez parametr shared_buffers. Domyślna przestrzeń pamięci buforów współdzielonych (bufor dysku współdzielonego) w wersji 9.2 i starszej to 32 megabajty (32 MB), od wersji 9,3 wartość domyślna to 128 megabajtów (128 MB).
Ilość pamięci RAM wymagana przez współdzielone bufory jest zawsze zablokowana dla instancji PostgreSQL podczas jej życia. Współdzielone bufory są dostępne dla wszystkich procesów serwera w tle i użytkowników łączących się z bazą danych.
Dane zapisywane lub modyfikowane w tej lokalizacji nazywane są „brudnymi danymi”, a jednostką działania są bloki (lub strony) bazy danych; zmodyfikowane bloki są również nazywane „brudnymi blokami” lub „brudnymi stronami”. Następnie brudne dane są zapisywane na dysku zawierającym pliki fizyczne w celu zapisania danych w trwałej lokalizacji, a pliki te są nazywane „plikami danych”.
Jeśli mamy serwer dedykowany dla PostgreSQL, rozsądnym początkiem ustawiania wartości buforów współdzielonych jest 25% całkowitej pamięci.
Bufor WAL
Bufor WAL (Bufor dziennika zapisu z wyprzedzeniem) to bufor, który tymczasowo przechowuje zmiany w bazie danych. Jest on również nazywany „buforem dziennika transakcji”. Dane WAL to informacje zawierające metadane opisujące zmiany w rzeczywistych danych, które są wystarczające do zrekonstruowania rzeczywistych danych podczas operacji odzyskiwania bazy danych. Dane WAL są zapisywane w zbiorze fizycznych plików w trwałej lokalizacji zwanej „segmentami WAL” lub „segmentami punktów kontrolnych”. Zawartość przechowywana w buforze WAL jest zapisywana w pliku WAL we wcześniej określonym momencie. Z punktu widzenia tworzenia kopii zapasowych i odzyskiwania bufory WAL i pliki WAL są niezwykle ważne, pozwalają bowiem odtworzyć historię modyfikacji danych (od ostatniego checkpointa, o którym powiemy dalej) w wypadku awarii.
Alokacja pamięci buforów WAL jest kontrolowana przez parametr wal_buffers i jest rezerwowana z pamięci RAM systemu operacyjnego. Chociaż ten obszar pamięci jest również dostępny dla wszystkich procesów serwera i użytkownika w tle, nie jest on częścią wspólnych buforów. Bufory WAL są zewnętrzne względem buforów współdzielonych i są od nich dużo mniejsze. Dane WAL są najpierw modyfikowane (brudne) w buforach WAL, zanim zostaną zapisane w segmentach WAL na dysku.
Minimalna wartość bufora WAL to 32 KB. Jeśli ustawimy ten parametr jako wal_buffers = -1, wartość zostanie ustawiona na podstawie shared_buffers. W takiej sytuacji rozmiar WAL Buffer jest przydzielany z rozmiarem 1/16 rozmiaru Shared buffers.
Bufory CLOG
CLOG to skrót od „commit log”, a bufory CLOG to obszar pamięci RAM systemu operacyjnego przeznaczony do przechowywania stron dziennika zatwierdzenia (commit log pages). Strony dziennika zatwierdzania zawierają dziennik metadanych transakcji i różnią się od danych WAL. Dzienniki zatwierdzenia przechowują status wszystkich transakcji i wskazują, czy transakcja została zakończona (zatwierdzona).
Nie ma określonego parametru sterującego tym obszarem pamięci. Jest on automatycznie zarządzany przez silnik bazy danych (rozmiar jest stosunkowo niewielki). Jest to składnik pamięci współdzielonej, który jest dostępny dla wszystkich serwerów działających w tle i procesów użytkownika bazy danych PostgreSQL.
Pamięć blokad
Ten składnik pamięci (Memory for Locks / Lock Space) służy do przechowywania wszystkich ciężkich blokad używanych przez instancję PostgreSQL. Blokady są współdzielone przez wszystkie serwery działające w tle i procesy użytkownika łączące się z bazą danych. Niedomyślne większe ustawienie dwóch parametrów bazy danych, mianowicie max_locks_per_transaction i max_pred_locks_per_transaction w pewien sposób wpływa na rozmiar tego składnika pamięci, aczkolwiek brak jest parametru bezpośrednio sterującego tym rozmiarem.
Pamięć procesowa
Pamięć procesowa (Process memory lub Local memory) jest ładowana na własny użytek przez każdy proces backendu do przetwarzania zapytań. Segment ten jest podzielony na podobszary:
Work Memory
Przestrzeń Work Memory jest wykorzystywana do obsługi połączeń klientów (dla każdego połączenia) oraz dla celów przetwarzania wewnętrznych operacji związanych z obsługą zapytań w zakresie pojedynczego sortowania lub operacji na tablicy mieszającej w zapytaniu. Operacja sortowania może być jedną z operacji łączenia ORDER BY, DISTINCT lub Merge, a operacja tablicy mieszającej może wynikać z łączenia mieszającego (hash-join), agregacji opartej na mieszaniu (hash based aggregation) lub podzapytania IN.
Rozmiar pamięci roboczej (dla pojedynczej operacji sortowania lub mieszania) jest kontrolowana przez parametr work_mem.
Pojedyncze złożone zapytanie może mieć wiele operacji sortowania lub mieszania, a dla każdej z tych operacji w połączeniu użytkownika zostanie utworzonych tyle samo fragmentów alokacji pamięci zdefiniowanych przez parametr work_mem. Z tego powodu work_mem nie powinien być deklarowany z bardzo dużą wartością, ponieważ może to prowadzić do agresywnego wykorzystania całej dostępnej pamięci z systemu operacyjnego dla znacznie większych zapytań, tym samym pozbawiając system operacyjny pamięci RAM, która może być potrzebna dla innych procesy.
Domyślna wartość pamięci roboczej w 9.3 i starszych wersjach to 1 megabajt (1 MB), zaś od wersji 9.4 domyślna wartość pamięci roboczej to 4 megabajty (4 MB).
Maintenance Work Memory
Kolejny segment pamięci jest zarezerwowany do obsługi „operacji utrzymania/ konserwacji bazy danych”, takich jak VACUUM, ANALYZE, ALTER TABLE, CREATE INDEX, ADD FOREIGN KEY itp.
Ustawienie jest kontrolowane przez parametr bazy danych maintenance_work_mem. Sesja bazy danych może wykonać tylko jedną z wyżej wymienionych operacji konserwacyjnych na raz, a instancja PostgreSQL zwykle nie wykonuje wielu takich operacji konserwacyjnych jednocześnie. Dlatego ten parametr może być ustawiony jako znacznie większy niż parametr work_mem. Należy uważać, aby nie ustawiać tej pamięci na bardzo wysoką wartość, która przydzieli tyle porcji alokacji pamięci, jak zdefiniowano w parametrze autovacuum_max_workers w przypadku nieskonfigurowania parametru autovacuum_work_mem.
Domyślna wartość pamięci roboczej utrzymania do wersji 9.3 to 16 megabajtów (16 MB), z kolei od 9.4 wartość domyślna pamięci roboczej to 64 megabajty (64 MB).
Bezpiecznie jest ustawić pamięć roboczą konserwacji, która jest odpowiednio większa w porównaniu do pamięci roboczej. Większe ustawienia poprawią wydajność operacji utrzymaniowych (VACUUM, ANALYZE, ALTER TABLE, CREATE INDEX, ADD FOREIGN KEY, itp.).
Bufor TEMP
Baza danych może mieć jedną lub więcej tabel tymczasowych, a bloki danych (strony) takich tabel tymczasowych wymagają osobnego przydziału pamięci. Bufory tymczasowe służą temu celowi, wykorzystując część pamięci RAM określoną przez parametr temp_buffers . Bufory tymczasowe są używane tylko do dostępu do tabel tymczasowych w sesji użytkownika.
Nie ma związku między buforami tymczasowymi w pamięci a plikami tymczasowymi tworzonymi w katalogu pgsql_tmp podczas operacji sortowania na dużą skalę i operacji na tablicach mieszających.
Architektura PostgreSQL – Procesy tła (backgroundowe)
W tle procesu Postmaster pracuje grupa procesów (tzw. backgroudowych), których funkcje podsumowano w tabeli:
Nazwa procesu | Funkcja realizowana przez dany proces |
---|---|
logger (SysLogger) | Zapisuje komunikaty PostgreSQL do plików dziennika zdarzeń |
checkpointer | Odpowiada za zapisywanie tzw. brudnego bufora do pliku w momencie gdy pojawia się punkt kontrolny |
writer (BgWriter) | Okresowo zapisuje brudny bufor do pliku. |
WAL writer (WalWriter) | Zapisz bufor WAL do pliku WAL |
autovacuum launcher | Tworzy i odpala (metodą fork) autovacuum worker, gdy funkcja autovacuum jest włączona. Demon autovacuum jest odpowiedzialny za przeprowadzanie na żądanie operacji opróżniania zaśmieconych tabel |
archiver (PgArch) | W trybie Archive.log kopiuje plik WAL do określonego katalogu |
stats collector (PgStat) | Zbiera statystyki użycia DBMS, takie jak informacje o wykonywaniu sesji ( pg_stat_activity ) i informacje statystyczne o wykorzystaniu tabel ( pg_stat_all_tables ). |
WAL sender i proces WAL receiver | Procesy strumieniowej replikacji danych pomiędzy bazami |
Writer proces
Proces Writer zapisuje w odpowiednim czasie pamięć podręczną przechowywaną w pamięci współdzielonej na dysk. Dzięki temu procesowi można zapobiec pogorszeniu się wydajności dużej liczby zapisów na dysku podczas punktu kontrolnego (check point), dzięki czemu serwer może utrzymać względnie stabilną wydajność. Writer proces jest obecny w pamięci od momentu uruchomienia go przez proces Postmaster, natomiast nie jest aktywny. Po aktywowaniu wykonuje przypisane zadania i ponownie przechodzi w tryb oczekiwania. Interwał uśpienia jest ustawiany przez parametr bgwriter_delay w postgresql.conf. Wartość domyślna to 200 mikrosekund.
Inną istotną funkcją tego procesu jest regularne wykonywanie punktów kontrolnych.
Podczas punktu kontrolnego zawartość pamięci podręcznej przechowywana w pamięci współdzielonej jest zapisywana w pliku bazy danych, dzięki czemu stan pamięci i pliku są spójne. W ten sposób można skrócić czas odzyskiwania z WAL w przypadku awarii systemu, a także zapobiec nieskończonemu wzrostowi WAL. Checkpoint_segments i checkpoint_timeout z postgresql.conf mogą być użyte do określenia przedziału czasu dla wykonywania punktów kontrolnych.
Podsumowując, proces Writer to proces, który zapisuje brudne strony w pamięci współdzielonej na dysk. Ma dwie funkcje:
- jedną jest okresowe opróżnianie brudnych danych z bufora pamięci na dysk w celu zmniejszenia blokowania podczas zapytania;
- drugą jest zapis wszystkich brudnych stron na dysk podczas regularnego punktu kontrolnego;
Zapisanie niektórych brudnych stron z wyprzedzeniem może zmniejszyć operacje IO, które należy wykonać podczas ustawiania punktów kontrolnych, dzięki czemu obciążenie systemu we/wy jest bardziej stabilne. BgWriter to nowa funkcja dodana po PostgreSQL 8.0. Jego mechanizmem można sterować konfigurując parametry zaczynające się od „bgwriter_” w pliku postgresql.conf:
Nazwa parametru | Opis |
---|---|
bgwriter_delay | Odstęp czasu między dwoma kolejnymi uruchomieniami procesu zapisywania w tle. Wartość domyślna to 200, a jednostką są milisekundy |
bgwriter_lru_maxpages | Maksymalna ilość danych zapisywanych jednocześnie przez proces zapisywania w tle. Wartość domyślna to 100 w jednostkach buforów. Jeśli ilość brudnych danych jest mniejsza niż ta wartość, operacja zapisu jest zakończona przez proces zapisu w tle; odwrotnie, gdy jest większa niż ta wartość, większa część zostanie ukończona przez proces serwera. Gdy wartość jest ustawiona na 0, oznacza to, że proces pisania w tle jest wyłączony i jest całkowicie wykonywany przez proces serwera; gdy jest ustawiony na -1, oznacza to, że wszystkie brudne dane są wykonywane przez background writer. (Operacje w punktach kontrolnych nie są tutaj uwzględnione) |
bgwriter_lru_multiplier | Parametr wskazuje ilość bloków danych zapisywanych na dysku za każdym razem, oczywiście wartość musi być mniejsza niż bgwriter_lru_maxpages. Jeśli ustawienie jest zbyt małe, ilość brudnych danych, które trzeba zapisać, jest większa niż ilość danych zapisywanych za każdym razem, więc pozostała praca, którą trzeba zapisać na dysk, musi zostać dokończona przez proces procesu serwera, co zmniejszy wydajność; jeśli konfiguracja wartości jest zbyt duża, ilość zapisanych brudnych danych większa niż liczba buforów wymaganych w danym czasie, co jest wygodne do późniejszego zastosowania pracy buforowej ale może tutaj wystąpić marnotrawstwo IO. Domyślna wartość tego parametru to 2,0.Metoda obliczania maksymalnych danych Bgwriter:1000/bgwriter_delaybgwriter_lru_maxpages8K=Maksymalna ilość danych |
bgwriter_flush_after | BgWriter jest wyzwalany, gdy rozmiar strony danych osiągnie bgwriter_flush_after, wartość domyślna to 512 KB. |
WAL writer
Proces zapisu WAL (pre-write log writing , czyli zapisywanie dziennika przed zapisem) zapisuje pamięć podręczną WAL przechowywaną we współużytkowanej pamięci na dysk. W ten sposób można zmniejszyć nacisk na proces zaplecza podczas zapisywania pamięci podręcznej WAL i poprawić wydajność. Ponadto, jeśli asynchroniczne zatwierdzanie (asynchronous commit) ma wartość prawda, można zapewnić, że zawartość pamięci podręcznej WAL zostanie zapisana w pliku dziennika WAL w określonym przedziale czasu.
Podstawową ideą dziennika zapisu z wyprzedzeniem (Write Ahead Log, znanego również jako Xlog) jest to, że modyfikacja pliku danych musi nastąpić dopiero po zarejestrowaniu tych modyfikacji w dzienniku, to znaczy, że dziennik jest zapisywany jako pierwszy a następnie dane są zapisywane w plikach z danymi (najpierw log) . Korzystanie z tego mechanizmu pozwala uniknąć częstego zapisywania danych na dysku i może zmniejszyć liczbę operacji we/wy dysku. Baza danych może użyć dzienników WAL do odzyskania bazy danych po ponownym uruchomieniu. Parametry związane z procesem WalWriter w pliku postgresql.conf są następujące:
Nazwa parametru | Opis |
---|---|
wal_level | Kontroluje poziom przechowywania WAL. wal_level określa, ile informacji jest zapisywanych w WAL. Wartość domyślna to minimalna, która zapisuje tylko informacje potrzebne do odzyskania systemu po awarii lub natychmiastowym zamknięciu. Replika dodaje informacje o archiwum Wal i zawiera informacje wymagane przez serwer tylko do odczytu. (Nowość w 9.6, scalanie archiwum i hot_standby z poprzedniej wersji) Logic jest używany głównie do logicznych scenariuszy dekodowania |
fsync | Parametr bezpośrednio kontroluje, czy dziennik jest najpierw zapisywany na dysku. Wartość domyślna to ON (najpierw zapis), co oznacza, że system musi czekać na zakończenie zapisu WAL, gdy zaktualizowane dane są zapisywane na dysku. Możesz ustawić ten parametr na OFF, co oznacza, że zaktualizowane dane są zapisywane na dysku bez oczekiwania na zakończenie zapisu WAL. |
synchronous_commit | Określa, czy konfiguracja parametrów czeka na zakończenie WAL przed zwróceniem informacji o stanie do transakcji użytkownika. Wartość domyślna to ON, co wskazuje, że informacje o statusie transakcji muszą zostać zwrócone po zakończeniu WAL; skonfigurowany na OFF może szybciej zwracać informacje o statusie transakcji. |
wal_sync_method | Metoda kontroli zapisu WAL na dysk. Wartość domyślna to fsync. Dostępne wartości obejmują open_datasync, fdatasync, fsync_writethrough, fsync i open_sync. open_datasync i open_sync używają odpowiednio flag O_DSYNC i O_SYNC podczas otwierania pliku WAL; fdatasync i fsync wywołują odpowiednio funkcje fdatasync i fsync do zapisywania danych przy każdym przesłaniu, obie funkcje zapisują pamięć podręczną dysku systemu operacyjnego z powrotem na dysk, ale pierwsza zapisuje tylko część danych pliku, podczas gdy druga również aktualizuje plik atrybuty synchronicznie; fsync_writethrough oznacza, że za każdym razem, gdy zatwierdzasz i zapisujesz z powrotem na dysku, zapewni to, że pamięć podręczna i pamięć podręczna dysku systemu operacyjnego mają tę samą zawartość. |
full_page_writes | Wskazuje, czy zapisać całą stronę do WAL |
wal_buffers | Rozmiar pamięci używanej do przechowywania danych WAL. Domyślna wartość systemowa to 64 KB. Na ten parametr mają również wpływ dwa parametry wal_writer_delay i commit_delay. |
wal_writer_delay | Interwał zapisu procesu WalWriter. Wartość domyślna to 200 milisekund. Zbyt długi czas może spowodować niewystarczającą ilość pamięci w buforze WAL; jeśli czas jest zbyt krótki, spowoduje to ciągły zapis WAL, zwiększając obciążenie I/O dysku. |
commit_delay | Wskazuje czas, w którym przesłane dane są przechowywane w buforze WAL. Wartość domyślna to 0 milisekund, co oznacza brak opóźnienia; gdy jest ustawiona na wartość niezerową, transakcja nie zostanie zapisana do WAL natychmiast po wykonaniu zatwierdzenia, ale nadal będzie przechowywana w WAL W buforze i będzie czekać aż proces WalWriter okresowo zapisze dane na dysku. |
commit_siblings | Gdy transakcja wysyła żądanie zatwierdzenia, jeśli liczba transakcji w bazie danych jest większa niż wartość commit_siblings, transakcja będzie czekać przez pewien czas (wartość commit_delay); w przeciwnym razie transakcja jest bezpośrednio zapisywana w WAL. Domyślna wartość systemowa to 5, a ten parametr określa również ważność commit_delay. |
wal_writer_flush_after | Gdy brudne dane przekroczą próg, zostaną opróżnione na dysk |
Archiver (proces PgArch)
Proces archiwizacji przenosi dzienniki WAL do dzienników archiwum. W przypadku zapisania (backupu) podstawowych dzienników kopii zapasowych i archiwalnych, nawet przy całkowitym uszkodzeniu dysku, można przywrócić bazę danych do najnowszego stanu.
Podobnie jak w przypadku procesu archiwizacji ARCH bazy danych Oracle, różnica polega na tym, że ARCH służy do archiwizacji logów ponownego przetwarzania, a PgArch do archiwizacji logów WAL.
Kiedy dziennik WAL zostanie przetworzony i zwrócony do ponownego użycia, oznacza to, że jego zawartość zostanie nadpisany przez nowo wygenerowany dziennik. Proces PgArch polega na utworzeniu kopii zapasowej dziennika WAL przed nadpisaniem.
Dziennik archiwum pozwala odtworzyć bazę danych do dowolnego punktu z przeszłości pod warunkiem, ze posiadamy pełną kopię zapasową bazy i kompletny dziennik archiwum wygenerowany od momentu utworzenia kopii zapasowej do momentu na który chcemy przywrócić stan bazy.
Od wersji PostgreSQL 8.X używaną technologią gromadzenia archiwum jest PITR (Point-In-Time-Recovery). Zachowanie procesu PgArch jest definiowane przez następujące parametry w pliku postgresql.conf:
Nazwa parametru | Opis |
---|---|
archive_mode | Wskazuje, czy wykonywać operację archiwizacji. Dopuszczalene wartości to off (wył.), on (start) i always (zawsze wł.), domyślną wartością jest off (wył.). |
archive_command | Polecenie ustawione przez administratora do archiwizacji dzienników WAL. W poleceniu archiwizacji predefiniowana zmienna „%p” jest używana w odniesieniu do nazwy pliku pełnej ścieżki WAL, który ma zostać zarchiwizowany, „%f” wskazuje nazwę pliku bez ścieżki (ścieżki tutaj są względne w stosunku do bieżącej ścieżki katalogu roboczego).Kiedy każdy plik segmentu WAL jest archiwizowany, zostanie wywołane polecenie określone przez archive_command. Gdy polecenie archiwum (archive_command ) zwraca 0, PostgreSQL uważa, że plik został pomyślnie zarchiwizowany, a następnie usuwa lub odtwarza plik segmentowy WAL. W przeciwnym razie, jeśli zwrócona zostanie wartość niezerowa, PostgreSQL założy, że plik nie został pomyślnie zarchiwizowany i będzie okresowo ponawiał próby, aż operacja się powiedzie. |
archive_timeout | Wskazuje okres archiwizacji. Po przekroczeniu czasu ustawionego w tym parametrze następuje wymuszone przełączenie segmentu WAL. Wartość domyślna to 0 (co oznacza, że funkcja jest wyłączona). |
Stats collector (proces zbierania statystyk, czyli PgStat)
Proces zbierania informacji statystycznych. Zbieraj informacje, takie jak liczba wizyt w tabeli statystyk oraz liczba wizyt na dysku. Zebrane informacje mogą być wykorzystywane przez autovaccum, a także jako informacje referencyjne do zarządzania bazą danych przez innych administratorów baz danych.
Służy również do zbierania informacji statystycznych z okresu działania bazy danych, takich jak liczba dodanych, usuniętych i zmienionych tabel, liczba bloków danych, zmiany w indeksach itp. Zbieranie informacji statystycznych służy głównie optymalizatorowi do prawidłowego określania i wyboru optymalnych planu wykonania. Parametry związane z procesem PgStat w pliku postgresql.conf są następujące:
Nazwa parametru | Opis |
---|---|
track_activities | Wskazuje, czy włączyć funkcję zbierania informacji statystycznych dla polecenia aktualnie wykonywanego w sesji. Ten parametr jest widoczny tylko dla superużytkownika i właściciela sesji. Wartość domyślna jest włączona. |
track_counts | Wskazuje, czy włączyć funkcję zbierania informacji statystycznych dla działań bazy danych. Ponieważ o czyszczeniu bazy danych decyduje proces automatycznego czyszczenia AutoVacuum, do podjęcia decyzji wymagane są informacje statystyczne bazy danych, dlatego domyślna wartość tego parametru jest włączona. |
track_io_timing | Rejestracja czasu wywołania operacji we/wy. Domyślnie jest wyłączony, ponieważ ustawiony na stan on będzie wielokrotnie sprawdzał czas bazy danych, co znacznie obciąża bazę. Tylko superużytkownik może ustawić tę wartość. |
track_functions | Wskazuje, czy włączyć rejestrację liczby wywołań funkcji i czasochłonne statystyki. |
track_activity_query_size | Ustawia liczbę bajtów używanych do śledzenia aktualnie wykonywanego polecenia każdej aktywnej sesji. Wartość domyślna to 1024. Inną wartość można ustawić dopiero po uruchomieniu bazy danych. |
stats_temp_directory | Ścieżka tymczasowego przechowywania informacji statystycznych. Ścieżka może być ścieżką względną lub bezwzględną. Domyślnym parametrem jest pg_stat_tmp. Ustawienie tego parametru może zmniejszyć fizyczne operacje we/wy bazy danych i poprawić wydajność. Ten parametr można zmodyfikować tylko w pliku postgresql.conf lub w wierszu poleceń serwera. |
Proces rejestratora (logger, SysLogger)
Proces zapisuje status oraz informacje o aktywności PostgreSQL w pliku dziennika (nie w dzienniku transakcji). Proces rotuje plik dziennika w określonym przedziale czasu.
Autovacuum launcher, czyli proces uruchamiania Autovacuum (automatycznego czyszczenia)
Proces uruchamiania automatycznego odśmiecania zawiaduje uruchamianiem zasadniczego procesu odśmiecania. Dzięki niemu Postmaster pośrednio uruchamia proces odśmiecania, a nie uruchamia go bezpośrednio. Dzięki temu ma się poprawić niezawodność systemu.
W bazie PostgreSQL, po wykonaniu na operacji UPDATE lub DELETE nie następuje od razu usunięcie starej wersji danych, ale dane takie zostają oznaczona jako usunięte. Dzieje się tak, ponieważ baza danych PostgreSQL ma mechanizm wersjonowania. Jeśli te stare wersje danych są otwierane przez inne transakcje, konieczne jest ich tymczasowe przechowywanie. Po przesłaniu transakcji stara wersja danych nie jest już wartościowa. Baza danych musi wyczyścić niepotrzebne dane, aby odzyskać niepotrzebnie zajęte miejsce, a prace porządkowe są wykonywane przez proces AutoVacuum. Parametry związane z procesem AutoVacuum w pliku postgresql.conf to:
Nazwa parametru | Opis |
---|---|
autovacuum | Wskazuje, czy uruchomić funkcję automatycznego czyszczenia systemu, domyślna wartość jest włączona. |
log_autovacuum_min_duration | Parametr służy do rejestrowania czasu wykonania autovacuum. Gdy czas wykonania autovacuum przekroczy ustawienie parametru log_autovacuum_min_duration, informacja o autovacuum jest zapisywana w logu. Wartość domyślna to „-1”, co oznacza brak nagrywania. |
autovacuum_max_workers | Ustawia maksymalną liczbę procesów roboczych automatycznego czyszczenia systemu. |
autovacuum_naptime | Ustaw odstęp czasu między dwoma automatycznymi operacjami czyszczenia systemu. |
autovacuum_vacuum_threshold | Gdy liczba zaktualizowanych krotek tabeli przekracza ten próg, należy wykonać odpowiednio odśmiecanie. |
autovacuum_analyze_threshold | Gdy liczba zaktualizowanych krotek tabeli przekracza ten próg, należy wykonać odpowiednio analizę. |
autovacuum_vacuum_scale_factor | Współczynnik skalowania dla rozmiaru tabeli. |
autovacuum_analyze_scale_factor | Współczynnik skalowania dla rozmiaru tabeli. |
autovacuum_freeze_max_age | Górny limit XID, który należy wymusić, aby wyczyścić bazę danych. |
autovacuum_vacuum_cost_delay | Kiedy proces autovacuum ma zostać wykonany, oceniany jest koszt wykonania czyszczenia. Jeśli wartość ustawiona przez autovacuum_vacuum_cost_limit zostanie przekroczona, wystąpi opóźnienie. Czas opóźnienia to autovacuum_vacuum_cost_delay. Jeśli wartość wynosi -1, używana jest wartość vacuum_cost_delay, a domyślna wartość to 20 ms. |
autovacuum_vacuum_cost_limit | Wartość jest progiem oceny procesu autovacuum. Wartość domyślna to -1, co oznacza użycie wartości „vacuum_cost_limit”. Jeśli koszt oszacowany podczas wykonywania procesu autovacuum przekroczy autovacuum_vacuum_cost_limit, proces autovacuum zostanie uśpiony. |
Autovacuum czyli automatyczny proces odśmiecania
Proces roboczy automatycznego odkurzania. Czasami wiele procesów odśmiecania jest uruchamianych w tym samym czasie.
WAL sender i proces WAL receiver czyli nadawca WAL /odbiornik WAL
Proces WAL sender i proces WAL receiver to procesy, które implementują replikację PostgreSQL (replikację strumieniową). Proces WAL sender przesyła logi WAL przez sieć, podczas gdy procesy WAL receiver innych instancji PostgreSQL otrzymują odpowiednie logi. Po otrzymaniu dziennika WAL, host PostgreSQL (zwany także Standby) procesu odbiornika WAL odtwarza go we własnej bazie danych i generuje bazę danych dokładnie taką samą jak PostgreSQL nadawcy (zwany również Master).
Proces CheckPoint (punkt kontrolny)
Punkt kontrolny to punkt sekwencji transakcji ustawiony przez system. Ustawienie punktu kontrolnego zapewnia, że informacje dziennika przed punktem kontrolnym zostaną opróżnione na dysk.
PostgreSQL jest jedną z baz danych, która opiera się na logu transakcyjnym z wyprzedzeniem (WAL) – wszystkie zmiany zapisywane są najpierw do logu (strumienia zmian), a dopiero potem do plików danych. Zapewnia to trwałość, ponieważ w przypadku awarii baza danych może użyć WAL do wykonania odzyskiwania – odczytać zmiany z WAL i ponownie zastosować je na plikach danych.
Chociaż może to podwoić liczbę zapisów, może również poprawić wydajność. Dzieje się tak ponieważ zapisy WAL mają charakter sekwencyjny, podczas gdy zapisy w plikach danych są często losowe.
Załóżmy, że system uległ awarii i baza danych musi wykonać odzyskiwanie. Najprostszym podejściem byłoby rozpoczęcie od zera i odtworzenie całego WAL od samego początku. W końcu powinniśmy otrzymać kompletną (i poprawną) bazę danych. Oczywistą wadą jest oczywiście konieczność zachowania i odtworzenia całego WAL-a. Często mamy do czynienia z bazami danych, które nie są bardzo duże (powiedzmy kilkaset GB), ale produkują nawet kilka TB WAL dziennie.
Aby zminimalizować rozmiar WAL zaprojektowano mechanizm punktów kontrolnych, w których baza danych może zagwarantować, że wszystkie zmiany dla danej pozycji WAL (przesunięcie w dzienniku) zostaną wyrzucone na dysk. Następnie może określić tę pozycję podczas odzyskiwania i odtworzyć tylko pozostałą część WAL, znacznie skracając czas odzyskiwania. Może również usunąć WAL przed tą „znaną dobrą” pozycją.
Aby zmiany w logu WAL zostały „zaaplikowane” do danych gromadzonych w bazie, w punkcie kontrolnym musi odbyć się proces przeniesienia zmian zgromadzonych w WAL do poprzedniej wersji danych zgromadzonych w plikach danych, co opisano już w pierwszej części artykułu. Proces CheckPoint zawiaduje operacjami związanymi z obsługą punktów kontrolnych.
Odpowiednie parametry pozwalające sterować automatycznymi punktami kontrolnymi znajdziemy w pliku postgresql.conf:
Nazwa parametru | Opis |
---|---|
checkpoint_segments | Określa maksymalną liczbę segmentów pliku dziennika (zwykle 16 MB), które można wypełnić między automatycznymi punktami kontrolnymi WAL. Punkt kontrolny WAL to punkt w sekwencji transakcji WAL, w którym gwarantuje się, że pliki danych zostały zaktualizowane o wszystkie informacje przed punktem kontrolnym. W tym momencie wszystkie brudne strony danych są usuwane na dysk, a rekord punktu kontrolnego jest zapisywany w pliku dziennika. Dzięki temu proces odzyskiwania po awarii może znaleźć najnowszy rekord punktu kontrolnego i zastosować wszystkie kolejne segmenty dziennika, aby zakończyć odzyskiwanie danych.Ponieważ proces punktu kontrolnego wymaga opróżnienia wszystkich brudnych stron danych na dysk, powoduje znaczne obciążenie we/wy. Zwiększenie tej wartości zapobiega nadmiernej liczbie punktów kontrolnych, chociaż może spowodować wolniejsze ponowne uruchamianie serwera w przypadku awarii.Wartość domyślna: 3 |
checkpoint_timeout | Maksymalny czas między automatycznymi punktami kontrolnymi WAL. Jeśli ta wartość jest określona bez jednostek, przyjmuje się ją jako sekundy. Prawidłowy zakres wynosi od 30 sekund do jednego dnia. Wartość domyślna to pięć minut (5min). Zwiększenie tego parametru może wydłużyć czas potrzebny na odzyskiwanie po awarii. Ten parametr można ustawić tylko w pliku postgresql.conf lub w wierszu poleceń serwera. |
checkpoint_completion_target | Czas spędzony na czyszczeniu brudnych buforów podczas punktu kontrolnego, jako ułamek interwału punktu kontrolnegoOkreśla cel ukończenia punktu kontrolnego jako ułamek całkowitego czasu między punktami kontrolnymi. Wartość domyślna to 0,9, która rozkłada punkt kontrolny na prawie cały dostępny interwał, zapewniając dość spójne obciążenie we/wy, a jednocześnie pozostawiając trochę czasu na ukończenie punktu kontrolnego. Zmniejszanie tego parametru nie jest zalecane, ponieważ powoduje to szybsze zakończenie punktu kontrolnego. Skutkuje to wyższą szybkością operacji we/wy w punkcie kontrolnym, po której następuje okres mniejszej liczby operacji we/wy między zakończeniem punktu kontrolnego a następnym zaplanowanym punktem kontrolnym. Ten parametr można ustawić tylko w pliku postgresql.conf lub w wierszu poleceń serwera. |
log_checkpoints | Powoduje, że punkty kontrolne i punkty restartu są rejestrowane w dzienniku serwera. Niektóre statystyki są zawarte w komunikatach dziennika, w tym liczba zapisanych buforów i czas poświęcony na ich zapisywanie. Ten parametr można ustawić tylko w pliku postgresql.conf lub w wierszu poleceń serwera. Domyślnie jest wyłączone. |
checkpoint_warning | Włącza ostrzeżenia informujące jeśli punkty kontrolne spowodowane wypełnianiem plików segmentowych WAL znajdują się bliżej siebie niż ten czas (co sugeruje, że należy podnieść max_wal_size). Jeśli ta wartość jest określona bez jednostek, przyjmuje się ją jako sekundy. Wartość domyślna to 30 sekund (30s). Zero wyłącza ostrzeżenie. Żadne ostrzeżenia nie będą generowane, jeśli checkpoint_timeout jest mniejszy niż checkpoint_warning. Ten parametr można ustawić tylko w pliku postgresql.conf lub w wierszu poleceń serwera. |
Punkt kontrolny można również wymusić poleceniem checkpoint. Tylko superużytkownik bazy danych może wywołać punkt kontrolny.
Ponadto punkt kontrolny może wystąpić „poza harmonogramem” wykonań automatycznych w następujących scenariuszach:
- Uruchamianie i restartowanie serwera PostgreSQL (pg_ctl STOP | RESTART).
- Żądanie COMMIT.
- Rozpoczęcie tworzenia kopii zapasowej bazy danych (pg_start_backup).
- Zatrzymywanie kopii zapasowej bazy danych (pg_stop_backup).
- Tworzenie bazy danych.
Architektura PostgreSQL – Procesy zaplecza (backendowe)
Postmaster jest odpowiedzialny za obsługę inicjalnych połączeń klientów. W tym celu stale nasłuchuje oczekując nowych połączeń na ściśle określonym porcie IP. Po odebraniu żądania połączenia wykonuje procedurę inicjalizacji, w skład której wchodzi zadanie takie jak uwierzytelnienie użytkownika, postmaster uruchamia dla każdego nowego połączenia nowy proces backendowy (proces zaplecza) do obsługi nowego klienta. Klient wchodzi w dalszą interakcję z serwerem PostgreSQL tylko poprzez przypisany mu proces zaplecza. W ramach tej interakcji następuje przesyłanie zapytań i odbieranie wyników zapytań. Opisane zachowanie pokazuje, że PostgreSQL pracuje w modelu Process-per-transaction.
Serwer zaplecza jest odpowiedzialny za wykonywanie zapytań przesłanych przez klienta poprzez wykonywanie określonych operacji. Każdy serwer zaplecza obsługuje tylko jedno zapytanie na raz.
Proces backendowy odpowiada również za zapis aktualizowanych danych w dzienniku transakcji (PostgreSQL nazywany jest dziennikiem WAL). Jest to używane głównie, gdy serwer nie działa, gdy zasilanie jest wyłączone, a także po ponownym uruchomieniu procesu odzyskiwania. Ponadto dziennik jest archiwizowany i może być używany, gdy wymagane jest odzyskanie. W PostgreSQL w wersjach powyżej 9.0 replikacja bazy danych może odbywać się w czasie rzeczywistym poprzez przeniesienie logów WAL do innego PostgreSQL. Jest to tak zwana funkcja „replikacji bazy danych”.
W tym samym czasie do systemu podłączonych jest wielu klientów, stąd wiele serwerów zaplecza wykonuje swoje zapytania jednocześnie. Serwer zaplecza uzyskuje dostęp do danych z puli buforów pamięci głównej, która jest umieszczona w pamięci współdzielonej.
Maksymalna liczba procesów zaplecza jest ustawiana przez parametr max_connections, a wartość domyślna tego parametru to 100. Proces zaplecza wykonuje żądanie zapytania przesłane z procesu użytkownika, a następnie odsyła wynik. Wykonanie zapytania wymaga operowania na przestrzeni pamięci serwera. O samej organizacji pamięci powiemy później, teraz natomiast należy zapamiętać, iż pamięć wykorzystywana do wykonywania zapytań nazywana jest pamięcią lokalną. Główne parametry związane z pamięcią lokalną to:
Nazwa parametru | Opis |
---|---|
work_mem | Przestrzeń używana do sortowania, operacji bitmapowych, łączeń mieszających (hash joins) i łączeń scalających (merge joins). Domyślne ustawienie to 4 MB. |
maintenance_work_mem | Przestrzeń wykorzystywana przez operację Vacuum i CREATE INDEX . Domyślne ustawienie to 64 MB. |
temp_buffers | Miejsce używane dla tabel tymczasowych. Domyślne ustawienie to 8 MB. |
Szczegóły flow procesów backendowych
Proces backendowy jest podprocesem procesu Postmaster (postgres) silnika bazy danych. Gdyby spojrzeć na niego od strony programistycznej, to główną funkcją backendu jest PostgresMain (tcop/postgres.c).
Architektura PostgreSQL – Odbieranie zapytania wysłanego przez interfejs (tekst SQL)
Tekst zapytania (kwerendy) SQL jest czystym (plain) tekstem i komputer nie może go zrozumieć, dlatego musi on zostać przekonwertowany na wewnętrzne drzewo parsera formularzy, które jest łatwiejsze w obsłudze. Ten proces nazywa się analizowaniem tekstu. Moduł analizy tekstu nazywa się parserem. Ten etap może wykorzystywać tylko informacje uzyskane dosłownie, więc dopóki nie ma błędów, takich jak błędy składniowe, nawet jeśli np. zaznaczenie nie istnieje, tabela nie zgłosi błędu. Drzewo kompozycji na tym etapie nazywa się surowym drzewem analizy. Punktem wejścia do przetwarzania kompozycji jest raw_parser (parser/parser.c).
Po przeanalizowaniu drzewa kompozycji jest ono konwertowane na drzewo zapytań. W tym momencie następuje dostęp do bazy danych w celu sprawdzenia, czy tabela istnieje, a jeśli tak, to nazwa tabeli jest konwertowana na OID. Przetwarzanie to nazywa się przetwarzaniem analizy (Analiza), a modułem przetwarzania analizy jest analizator. Dodatkowo, gdy kod PostgreSQL odwołuje się do drzewa parsera, częściej odnosi się do Drzewa zapytań. Punkt wejścia modułu przetwarzania analizy znajduje się w parse_analyze (parser/analyze.c)
PostgreSQL implementuje również widoki i reguły poprzez przepisywanie zapytań, więc gdy zajdzie taka potrzeba, zapytania zapytań zostaną przepisane na tym etapie. Ten proces nazywa się przepisywaniem. Punktem wejścia do przepisywania jest QueryRewrite (rewrite/rewriteHandler.c).
Analizując drzewo zapytań, można faktycznie wygenerować drzewo planu. Proces generowania drzewa zapytań nazywa się „przetwarzaniem planu wykonania”, a najważniejszą rzeczą jest wygenerowanie drzewa planu, którego wykonanie można oszacować w jak najkrótszym czasie. Ten krok nazywa się „optymalizacją zapytań”, a moduł, który kończy ten proces, nazywa się optymalizatorem zapytań. Punktem wejścia do przetwarzania planu wykonania jest standard_planner (optimizer/plan/planner.c).
Idąc zgodnie z instrukcjami w planie wykonania, realizujemy cel zapytania. Proces uruchamiania kroków w drzewie planu wykonania nazywany jest procesem wykonania „execute”, a moduł, który kończy ten proces, nazywany jest executorem „Executor”. Adres wejściowy executora to ExecutorRun (executor/execMain.c)
Struktura danych PostgreSQL…
Po więcej informacji zapraszamy na szkolenie!!!
Artykuły na dev-academy.pl