Jako administrator bazy danych PostgreSQL, codziennie oczekujesz sprawdzania kopii zapasowych, wprowadzania zmian DDL, upewniania się, że w dziennikach nie ma żadnej gry łamiącej błędy ERROR i odpowiadania na spanikowane telefony od programistów, których raporty działają dwa razy dłużej niż normalnie i mieć spotkanie za dziesięć minut.
Nawet przy dobrym zrozumieniu kondycji zarządzanych baz danych zawsze będą pojawiać się nowe przypadki i nowe problemy związane z wydajnością i „odczuciem” bazy danych. Niezależnie od tego, czy jest to spanikowana wiadomość e-mail, czy otwarte zgłoszenie „baza danych wydaje się powolna”, to powszechne zadanie można ogólnie wykonać, wykonując kilka kroków, aby sprawdzić, czy występuje problem z PostgreSQL i jaki może to być problem.
Nie jest to w żadnym stopniu wyczerpujący przewodnik, a kroki nie muszą być wykonywane w określonej kolejności. Ale jest to raczej zestaw wstępnych kroków, które można podjąć, aby szybko znaleźć wspólnych przestępców, a także uzyskać nowy wgląd w to, na czym może polegać problem. Deweloper może wiedzieć, jak aplikacja działa i reaguje, ale administrator bazy danych wie, jak działa baza danych i reaguje na aplikację, i razem można znaleźć problem.
UWAGA: Zapytania do wykonania powinny być wykonywane jako superużytkownik, np. „postgres” lub dowolny użytkownik bazy danych z uprawnieniami superużytkownika. Użytkownicy z ograniczeniami zostaną odrzuceni lub zostaną pominięci dane.
Krok 0 – Zbieranie informacji
Uzyskaj jak najwięcej informacji od każdego, kto twierdzi, że baza danych wydaje się powolna; konkretne zapytania, połączone aplikacje, ramy czasowe spowolnienia wydajności itp. Im więcej informacji podadzą, tym łatwiej będzie znaleźć problem.
Krok 1 – Sprawdź pg_stat_activity
Żądanie może przybierać różne formy, ale jeśli „powolność” jest ogólnym problemem, sprawdzenie pg_stat_activity jest pierwszym krokiem do zrozumienia, co się dzieje. Widok pg_stat_activity (dokumentację dla każdej kolumny w tym widoku można znaleźć tutaj) zawiera wiersz dla każdego procesu serwera / połączenia z bazą danych od klienta. W tym widoku znajduje się garść przydatnych informacji, które mogą pomóc.
UWAGA: Wiadomo, że pg_stat_activity zmienia strukturę z biegiem czasu, poprawiając prezentowane dane. Zrozumienie samych kolumn pomoże w dynamicznym tworzeniu zapytań zgodnie z potrzebami w przyszłości.
Godne uwagi kolumny w pg_stat_activity to:
- zapytanie:kolumna tekstowa pokazująca zapytanie, które jest aktualnie wykonywane, oczekuje na wykonanie lub zostało wykonane ostatnio (w zależności od stanu). Może to pomóc w określeniu, które zapytania/zapytania, które programista może zgłaszać, działają powoli.
- client_addr:adres IP, z którego pochodzi to połączenie i zapytanie. Jeśli jest pusty (lub Null), pochodzi z localhost.
- backend_start, xact_start, query_start:te trzy zapewniają odpowiednio sygnaturę czasową, kiedy każdy z nich został uruchomiony. Backend_start oznacza, kiedy połączenie z bazą danych zostało ustanowione, xact_start oznacza rozpoczęcie bieżącej transakcji, a query_start oznacza rozpoczęcie bieżącego (lub ostatniego) zapytania.
- stan:stan połączenia z bazą danych. Aktywny oznacza, że aktualnie wykonuje zapytanie, „bezczynny” oznacza, że czeka na dalsze dane od klienta, „bezczynny w transakcji” oznacza, że czeka na dalsze dane wejściowe od klienta, trzymając otwartą transakcję. (Istnieją inne, jednak ich prawdopodobieństwo jest rzadkie, zapoznaj się z dokumentacją, aby uzyskać więcej informacji).
- nazwa_danych:Nazwa bazy danych, z którą połączenie jest aktualnie połączone. W wielu klastrach baz danych może to pomóc w izolowaniu problematycznych połączeń.
- wait_event_type i wait_event:te kolumny będą miały wartość null, gdy zapytanie nie czeka, ale jeśli czeka, będą zawierać informacje o tym, dlaczego zapytanie czeka, a eksploracja pg_locks może zidentyfikować, na co czeka. (PostgreSQL 9.5 i wcześniejsze ma tylko kolumnę logiczną o nazwie „oczekiwanie”, prawda, jeśli czeka, fałsz, jeśli nie.
1.1. Czy zapytanie czeka / jest zablokowane?
Jeśli istnieje konkretne zapytanie lub zapytania, które są „wolne” lub „zawieszone”, sprawdź, czy nie czekają na zakończenie innego zapytania. Ze względu na blokowanie relacji inne zapytania mogą blokować tabelę i nie pozwalać innym zapytaniom na dostęp lub zmianę danych, dopóki to zapytanie lub transakcja nie zostaną wykonane.
PostgreSQL 9.5 i wcześniejsze:
SELECT * FROM pg_stat_activity WHERE waiting = TRUE;
PostgreSQL 9.6:
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;
PostgreSQL 10 i nowsze (?):
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';
Wyniki tego zapytania pokażą wszystkie połączenia oczekujące aktualnie na inne połączenie, aby zwolnić blokady na potrzebnej relacji.
Jeśli zapytanie jest blokowane przez inne połączenie, istnieje kilka sposobów, aby dowiedzieć się, czym one są. W PostgreSQL 9.6 i nowszych funkcja pg_blocking_pids() umożliwia wprowadzenie identyfikatora procesu, który jest blokowany, i zwróci tablicę identyfikatorów procesu, które są odpowiedzialne za jego blokowanie.
PostgreSQL 9.6 i nowsze:
SELECT * FROM pg_stat_activity
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));
PostgreSQL 9.5 i wcześniejsze:
SELECT blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS current_statement_in_blocking_process
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.GRANTED;
(Dostępne na Wiki PostgreSQL).
Te zapytania wskażą wszystko, co blokuje określony PID, który jest podany. Dzięki temu można podjąć decyzję o zamknięciu zapytania lub połączenia blokującego lub pozostawieniu go do działania.
Krok 2 — Jeśli zapytania są uruchomione, dlaczego trwają tak długo?
2.1. Czy planista sprawnie wykonuje zapytania?
Jeśli dane zapytanie (lub zestaw zapytań) ma status „aktywne”, to faktycznie jest uruchomione. Jeśli całe zapytanie nie jest dostępne w pg_stat_activity, pobierz je od programistów lub dziennika postgresql i zacznij przeglądać planer zapytań.
EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop (cost=0.280..1328182.030 rows=2127135 width=335)
-> Index Scan using six on victor_oscar echo (cost=0.280..8.290 rows=1 width=71)
Index Cond: (india_romeo = 569)
-> Append (cost=0.000..1306902.390 rows=2127135 width=264)
-> Seq Scan on india_echo romeo (cost=0.000..0.000 rows=1 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on juliet victor_echo (cost=0.000..437153.700 rows=711789 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on india_papa quebec_bravo (cost=0.000..434936.960 rows=700197 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on two oscar (cost=0.000..434811.720 rows=715148 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
W tym przykładzie przedstawiono plan kwerendy dla sprzężenia dwóch tabel, który również trafia na tabelę podzieloną na partycje. Szukamy wszystkiego, co może spowolnić zapytanie, a w tym przypadku planista wykonuje kilka skanowań sekwencyjnych na partycjach, sugerując, że brakuje im indeksów. Dodanie indeksów do tych tabel dla kolumny „india_romeo” natychmiast poprawi to zapytanie.
Rzeczy, których należy szukać, to skanowanie sekwencyjne, zagnieżdżone pętle, drogie sortowanie itp. Zrozumienie planowania zapytań ma kluczowe znaczenie dla upewnienia się, że zapytania działają w najlepszy możliwy sposób, oficjalną dokumentację można przeczytać tutaj, aby uzyskać więcej informacji.
2.2. Czy stoły są nadęte?
Jeśli zapytania nadal są powolne, a planer zapytań nie wskazuje na coś oczywistego, czas sprawdzić kondycję zaangażowanych tabel. Czy są za duże? Czy są wzdęci?
SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup | n_dead_tup
------------+------------
15677 | 8275431
(1 row)
Tutaj widzimy, że jest wiele razy więcej martwych wierszy niż żywych, co oznacza, że aby znaleźć prawidłowe wiersze, silnik musi przesiać dane, które nie są nawet istotne, aby znaleźć prawdziwe dane. Podciśnienie/podciśnienie pełne na tym stole znacznie zwiększy wydajność.
Krok 3 — Sprawdź dzienniki
Jeśli nadal nie można znaleźć problemu, sprawdź dzienniki pod kątem jakichkolwiek wskazówek.
Komunikaty KRYTYCZNE/BŁĄD:
Poszukaj wiadomości, które mogą powodować problemy, takie jak zakleszczenia lub długie czasy oczekiwania na blokadę.
Punkty kontrolne
Mam nadzieję, że log_checkpoints jest włączone, co spowoduje zapisanie w dziennikach informacji o punktach kontrolnych. Istnieją dwa rodzaje punktów kontrolnych:czasowe i wymagane (wymuszone). Jeśli punkty kontrolne są wymuszane, brudne bufory w pamięci muszą zostać zapisane na dysku przed przetworzeniem większej liczby zapytań, co może dać systemowi bazy danych ogólne wrażenie „powolności”. Zwiększenie checkpoint_segments lub max_wal_size (w zależności od wersji bazy danych) da wskaźnikowi kontrolnemu więcej miejsca do pracy, a także pomoże twórcy w tle przejąć część obciążenia związanego z pisaniem.
Krok 4 – Jaka jest kondycja systemu hosta?
Jeśli w samej bazie danych nie ma żadnych wskazówek, być może sam host jest przeciążony lub ma problemy. Wszystko, od przeciążonego kanału we/wy na dysk, przepełnienia pamięci do wymiany, a nawet awarii dysku, żaden z tych problemów nie byłby widoczny w przypadku niczego, na co patrzyliśmy wcześniej. Zakładając, że baza danych działa w systemie operacyjnym opartym na *nix, oto kilka rzeczy, które mogą pomóc.
4.1. Obciążenie systemu
Używając „góry”, spójrz na średnie obciążenie hosta. Jeśli liczba zbliża się lub przekracza liczbę rdzeni w systemie, może to być po prostu zbyt wiele jednoczesnych połączeń uderzających w bazę danych, co powoduje jej przeszukiwanie, aby nadrobić zaległości.
load average: 3.43, 5.25, 4.85
4.2. Pamięć systemowa i SWAP
Używając opcji „bezpłatny”, sprawdź, czy w ogóle zastosowano SWAP. Przepełnienie pamięci do SWAP w środowisku bazy danych PostgreSQL jest bardzo złe dla wydajności, a wielu administratorów baz danych wyeliminuje nawet SWAP z hostów baz danych, ponieważ błąd „braku pamięci” jest bardziej preferowany niż powolny system.
Jeśli używany jest SWAP, ponowne uruchomienie systemu wyczyści go, a zwiększenie całkowitej pamięci systemowej lub ponowna konfiguracja użycia pamięci dla PostgreSQL (np. obniżenie shared_buffers lub work_mem) może być w porządku.
[[email protected] ~]$ free -m
total used free shared buff/cache available
Mem: 7986 225 1297 12 6462 7473
Swap: 7987 2048 5939
4.3. Dostęp do dysku
PostgreSQL usiłuje wykonać wiele swojej pracy w pamięci i rozłożyć zapis na dysk, aby zminimalizować wąskie gardła, ale w przeciążonym systemie z intensywnym zapisem łatwo jest zauważyć, że ciężkie odczyty i zapisy powodują spowolnienie całego systemu w miarę nadrabiania zaległości na żądanie. Szybsze dyski, więcej dysków i kanałów IO to kilka sposobów na zwiększenie ilości pracy, którą można wykonać.
Narzędzia takie jak „iostat” lub „iotop” mogą pomóc określić, czy istnieje wąskie gardło dysku i skąd może ono pochodzić.
4.4. Sprawdź dzienniki
Jeśli wszystko inne zawiedzie, a nawet jeśli nie, należy zawsze sprawdzać dzienniki, aby sprawdzić, czy system zgłasza coś, co jest nie tak. Omówiliśmy już sprawdzanie postgresql.logs, ale dzienniki systemowe mogą dostarczać informacji o problemach, takich jak awaria dysków, awaria pamięci, problemy z siecią itp. Każdy z tych problemów może spowodować, że baza danych będzie działać wolno i nieprzewidywalnie, więc dobre zrozumienie doskonałego zdrowia może pomóc w znalezieniu tych problemów.
Pobierz oficjalny dokument już dziś Zarządzanie i automatyzacja PostgreSQL za pomocą ClusterControlDowiedz się, co musisz wiedzieć, aby wdrażać, monitorować, zarządzać i skalować PostgreSQLPobierz oficjalny dokumentKrok 5 – Coś wciąż nie ma sensu?
Nawet najbardziej doświadczeni administratorzy natkną się na coś nowego, co nie ma sensu. Tutaj z pomocą może przyjść globalna społeczność PostgreSQL. Podobnie jak w kroku #0, im bardziej przejrzyste informacje są przekazywane społeczności, tym łatwiej mogą im pomóc.
5.1. Listy mailingowe PostgreSQL
Ponieważ PostgreSQL jest rozwijany i zarządzany przez społeczność open source, tysiące ludzi rozmawia przez listy mailingowe, aby omawiać niezliczone tematy, w tym funkcje, błędy i problemy z wydajnością. Listy mailingowe można znaleźć tutaj, przy czym pgsql-admin i pgsql-performance są najważniejsze przy szukaniu pomocy w przypadku problemów z wydajnością.
5.2. IRC
Freenode obsługuje kilka kanałów PostgreSQL z programistami i administratorami na całym świecie i nie jest trudno znaleźć pomocną osobę, która mogłaby wyśledzić, skąd mogą pochodzić problemy. Więcej informacji można znaleźć na stronie IRC PostgreSQL.