Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Proponuję przeczytać transkrypcję raportu z początku 2016 roku autorstwa Andreya Salnikova „Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql”

W tym raporcie przeanalizuję główne błędy w aplikacjach, które powstają na etapie projektowania i pisania kodu aplikacji. I wezmę tylko te błędy, które prowadzą do wzdęć w Postgresql. Z reguły jest to początek końca wydajności Twojego systemu jako całości, choć początkowo nie było widać żadnych przesłanek ku temu.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Miło mi wszystkich powitać! To sprawozdanie nie jest tak techniczne jak poprzednie, przygotowane przez mojego kolegę. Ten raport jest skierowany głównie do programistów systemów backendowych, ponieważ mamy dość dużą liczbę klientów. I wszyscy popełniają te same błędy. Opowiem Ci o nich. Wyjaśnię, do jakich fatalnych i złych rzeczy prowadzą te błędy.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Dlaczego popełniane są błędy? Robi się je z dwóch powodów: losowo, może się uda oraz z powodu nieznajomości niektórych mechanizmów zachodzących na poziomie pomiędzy bazą danych a aplikacją, a także w samej bazie danych.

Podam trzy przykłady ze strasznymi obrazami tego, jak źle się sprawy potoczyły. Pokrótce opowiem o mechanizmie, który tam zachodzi. Oraz jak sobie z nimi radzić, kiedy do nich doszło i jakie metody zapobiegawcze stosować, aby zapobiec błędom. Opowiem Ci o narzędziach pomocniczych i podam przydatne linki.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Użyłem testowej bazy danych, w której miałem dwie tabele. Jedna tabliczka z rachunkami klientów, druga z transakcjami na tych rachunkach. Z pewną częstotliwością aktualizujemy salda na tych rachunkach.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Początkowe dane płyty: jest dość mała, 2 MB. Czas reakcji bazy danych, a zwłaszcza znaku, jest również bardzo dobry. I całkiem niezłe obciążenie - według tabliczki 2 operacji na sekundę.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Za pośrednictwem tego raportu pokażę ci wykresy, abyś mógł jasno zrozumieć, co się dzieje. Zawsze będą 2 slajdy z wykresami. Pierwszy slajd przedstawia ogólnie to, co dzieje się na serwerze.

I w tej sytuacji widzimy, że naprawdę mamy mały znak. Indeks jest mały i ma 2 MB. To jest pierwszy wykres po lewej stronie.

Średni czas odpowiedzi na serwerze jest również stabilny i krótki. To jest prawy górny wykres.

Wykres w lewym dolnym rogu pokazuje najdłuższe transakcje. Widzimy, że transakcje są realizowane szybko. A tu jeszcze autovacuum nie działa, bo to był start próbny. Będzie nadal działać i będzie dla nas przydatny.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Drugi slajd będzie zawsze poświęcony testowanej płycie. W tej sytuacji na bieżąco aktualizujemy salda rachunków Klienta. Widzimy, że średni czas odpowiedzi na operację aktualizacji jest całkiem dobry i wynosi mniej niż milisekundę. Widzimy, że zasoby procesora (to jest prawy górny wykres) również są zużywane równomiernie i dość małe.

Prawy dolny wykres pokazuje, ile pamięci operacyjnej i dyskowej przechodzimy w poszukiwaniu pożądanej linii przed jej aktualizacją. A liczba operacji według znaku wynosi 2 na sekundę, jak powiedziałem na początku.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

A teraz mamy tragedię. Z jakiegoś powodu jest dawno zapomniana transakcja. Powody są zazwyczaj banalne:

  • Jednym z najczęstszych jest to, że dostęp do usługi zewnętrznej rozpoczęliśmy w kodzie aplikacji. I ta usługa nam nie odpowiada. Oznacza to, że otworzyliśmy transakcję, dokonaliśmy zmiany w bazie danych i przeszliśmy z aplikacji do czytania poczty lub do innej usługi w ramach naszej infrastruktury i z jakiegoś powodu nam nie odpowiada. A nasza sesja utknęła w stanie, w którym nie wiadomo kiedy zostanie rozwiązana.
  • Druga sytuacja ma miejsce, gdy z jakiegoś powodu w naszym kodzie wystąpił wyjątek. I w wyjątku nie przetworzyliśmy zamknięcia transakcji. I zakończyliśmy sesją wiszącą z otwartą transakcją.
  • I to ostatnie też jest dość częstym przypadkiem. To jest kod niskiej jakości. Niektóre frameworki otwierają transakcję. Zawiesza się i możesz nie wiedzieć w aplikacji, że się zawiesił.

Dokąd prowadzą takie rzeczy?

Do tego stopnia, że ​​nasze tabele i indeksy zaczynają dramatycznie puchnąć. To jest dokładnie ten sam efekt wzdęcia. Dla bazy danych będzie to oznaczać, że czas odpowiedzi bazy danych bardzo gwałtownie wzrośnie i zwiększy się obciążenie serwera bazy danych. W rezultacie nasza aplikacja ucierpi. Ponieważ jeśli poświęciłeś 10 milisekund w kodzie na żądanie do bazy danych, 10 milisekund na logikę, wówczas wykonanie funkcji zajęło 20 milisekund. A teraz twoja sytuacja będzie całkowicie smutna.

Zobaczmy, co się stanie. Lewy dolny wykres pokazuje, że mamy długą, długą transakcję. A jeśli spojrzymy na lewy górny wykres, zobaczymy, że rozmiar naszej tabeli nagle wzrósł z dwóch megabajtów do 300 megabajtów. Jednocześnie ilość danych w tabeli nie uległa zmianie, czyli jest tam dość duża ilość śmieci.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

O kilka rzędów wielkości zmieniła się także ogólna sytuacja dotycząca średniego czasu odpowiedzi serwera. Oznacza to, że wszystkie żądania na serwerze zaczęły całkowicie spadać. Jednocześnie uruchomiono wewnętrzne procesy Postgresa w postaci autovacuum, które próbują coś zrobić i zużywają zasoby.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Co się dzieje z naszym znakiem? Ten sam. Nasz średni czas reakcji według znaku wzrósł o kilka rzędów wielkości. W szczególności pod względem zużytych zasobów widzimy, że obciążenie procesora znacznie wzrosło. To jest prawy górny wykres. I wzrosła, ponieważ procesor musi sortować kilka bezużytecznych linii w poszukiwaniu tej potrzebnej. To jest prawy dolny wykres. I w rezultacie nasza liczba połączeń na sekundę zaczęła bardzo znacząco spadać, ponieważ baza danych nie miała czasu przetworzyć takiej samej liczby żądań.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Musimy wrócić do życia. Wchodzimy do Internetu i dowiadujemy się, że długie transakcje prowadzą do problemów. Znajdujemy i zabijamy tę transakcję. I wszystko staje się dla nas normalne. Wszystko działa jak powinno.

Uspokoiliśmy się, jednak po chwili zaczynamy zauważać, że aplikacja nie działa już tak samo jak przed stanem awaryjnym. Żądania są nadal przetwarzane wolniej i znacznie wolniej. W moim przykładzie półtora do dwóch razy wolniej. Obciążenie serwera jest również większe niż przed wypadkiem.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

I pytanie: „Co się w tej chwili dzieje z bazą?” A następująca sytuacja ma miejsce z bazą. Na wykresie transakcyjnym widać, że została zatrzymana i tak naprawdę nie ma tam transakcji długoterminowych. Ale rozmiar znaku śmiertelnie wzrósł podczas wypadku. I od tego czasu nie spadły. Średni czas przebywania w bazie ustabilizował się. Wydaje się, że odpowiedzi nadchodzą w odpowiednim dla nas tempie. Automatyczna próżnia stała się bardziej aktywna i zaczęła coś robić ze znakiem, bo musi przesiać więcej danych.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Konkretnie, jak wynika z płytki testowej z rachunkami, gdzie zmieniamy salda: czas odpowiedzi na żądanie wydaje się wrócić do normy. Ale w rzeczywistości jest półtora razy wyższy.

Z obciążenia procesora widzimy, że obciążenie procesora nie wróciło do wymaganej wartości przed awarią. Przyczyny leżą dokładnie na prawym dolnym wykresie. Widać, że przeszukiwana jest tam pewna ilość pamięci. Oznacza to, że aby znaleźć wymaganą linię, marnujemy zasoby serwera bazy danych podczas sortowania bezużytecznych danych. Liczba transakcji na sekundę ustabilizowała się.

Ogólnie dobrze, ale sytuacja jest gorsza niż była. Wyraźna degradacja bazy danych w wyniku naszej aplikacji współpracującej z tą bazą danych.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

A żeby zrozumieć, co się tam dzieje, jeśli nie byliście przy poprzednim raporcie, teraz trochę teorii. Teoria procesu wewnętrznego. Dlaczego odkurzacz samochodowy i do czego służy?

Dosłownie krótko dla zrozumienia. W pewnym momencie mamy stół. Mamy wiersze w tabeli. Linie te mogą być aktywne, żywe i takie, jakich teraz potrzebujemy. Na zdjęciu zaznaczono je kolorem zielonym. A są terminy, które zostały już wypracowane, zostały zaktualizowane i pojawiły się na nich nowe wpisy. I są zaznaczane, że nie są już interesujące dla bazy danych. Ale znajdują się w tabeli dzięki funkcji Postgres.

Dlaczego potrzebujesz odkurzacza samochodowego? W pewnym momencie przychodzi autovacuum, uzyskuje dostęp do bazy danych i pyta: „Proszę o podanie identyfikatora najstarszej transakcji, która jest aktualnie otwarta w bazie danych”. Baza danych zwraca ten identyfikator. A automatyczna próżnia, opierając się na tym, sortuje linie w tabeli. A jeśli widzi, że niektóre linie zostały zmienione przez znacznie starsze transakcje, to ma prawo oznaczyć je jako linie, które będziemy mogli ponownie wykorzystać w przyszłości, wpisując tam nowe dane. Jest to proces w tle.

W tym momencie kontynuujemy pracę z bazą danych i wprowadzamy pewne zmiany w tabeli. I na tych liniach, które możemy ponownie wykorzystać, zapisujemy nowe dane. I tak otrzymujemy cykl, czyli cały czas pojawiają się tam jakieś martwe stare linie, zamiast nich dopisujemy nowe potrzebne nam linie. Jest to normalny stan działania PostgreSQL.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Co się stało podczas wypadku? Jak tam przebiegał ten proces?

Mieliśmy znak w pewnym stanie, część pod napięciem, część martwa. Przyjechał odkurzacz samochodowy. Zapytał bazę, jaka jest nasza najstarsza transakcja i jaki jest jej identyfikator. Otrzymałem ten identyfikator, który mógł być wiele godzin temu, może dziesięć minut temu. Zależy to od tego, jak duże jest obciążenie bazy danych. I poszedł szukać linii, które mógłby oznaczyć jako ponownie użyte. I nie znalazłem takich linii w naszym stole.

Ale w tej chwili nadal pracujemy ze stołem. Robimy w nim coś, aktualizujemy, zmieniamy dane. Co w tym momencie powinna zrobić baza danych? Nie ma innego wyjścia, jak tylko dodać nowe linie na końcu istniejącej tabeli. I w ten sposób rozmiar naszego stołu zaczyna puchnąć.

W rzeczywistości potrzebujemy zielonych linii, aby zadziałały. Ale podczas takiego problemu okazuje się, że procent zielonych linii jest wyjątkowo niski w całej tabeli.

A kiedy wykonujemy zapytanie, baza danych musi przejść przez wszystkie linie: czerwoną i zieloną, aby znaleźć żądaną linię. A efekt rozdęcia tabeli bezużytecznymi danymi nazywany jest „wzdęciem”, co również zjada nasze miejsce na dysku. Pamiętasz, to było 2 MB, stało się 300 MB? Teraz zamień megabajty na gigabajty, a szybko stracisz wszystkie zasoby dysku.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Jakie mogą być dla nas konsekwencje?

  • W moim przykładzie tabela i indeks wzrosły 150 razy. Niektórzy z naszych klientów mieli więcej śmiertelnych przypadków, gdy po prostu zaczęło brakować im miejsca na dysku.
  • Rozmiar samych stołów nigdy się nie zmniejszy. Autovacuum w niektórych przypadkach może odciąć ogon stołu, jeśli są tylko martwe linie. Ponieważ jednak występuje ciągła rotacja, jedna zielona linia może zamarznąć na końcu i nie zostać zaktualizowana, podczas gdy wszystkie pozostałe zostaną zapisane gdzieś na początku tablicy. Ale jest to tak mało prawdopodobne, że Twój stół zmniejszy się, więc nie powinieneś na to liczyć.
  • Baza danych musi przesortować całą masę bezużytecznych linii. I marnujemy zasoby dyskowe, marnujemy zasoby procesora i energię elektryczną.
  • A to ma bezpośredni wpływ na naszą aplikację, bo jeśli na początku spędziliśmy 10 milisekund na żądanie, 10 milisekund na naszym kodzie, to w czasie awarii zaczęliśmy spędzać sekundę na żądaniu i 10 milisekund na kodzie, czyli kolejność spadła wydajność aplikacji. A kiedy awaria została rozwiązana, zaczęliśmy poświęcać 20 milisekund na żądanie i 10 milisekund na kod. Oznacza to, że produktywność i tak spadła półtorakrotnie. A to wszystko przez jedną transakcję, która została zamrożona, być może z naszej winy.
  • I pytanie: „Jak możemy wszystko odzyskać?”, żeby wszystko było u nas w porządku, a prośby spływały tak szybko, jak przed wypadkiem.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

W tym celu wykonywany jest określony cykl pracy.

Najpierw musimy znaleźć problematyczne tabele, które są nadęte. Rozumiemy, że w niektórych tabelach zapis jest bardziej aktywny, w innych mniej aktywny. I do tego używamy rozszerzenia pgstattuple. Instalując to rozszerzenie, możesz pisać zapytania, które pomogą Ci znaleźć dość rozdęte tabele.

Po znalezieniu tych tabel należy je skompresować. Istnieją już do tego narzędzia. W naszej firmie posługujemy się trzema narzędziami. Pierwsza to wbudowana funkcja VACUUM FULL. Jest okrutny, surowy i bezlitosny, ale czasami jest bardzo przydatny. Pg_przepakuj и pgkompaktowy - Są to narzędzia innych firm do kompresji tabel. I ostrożniej traktują bazę danych.

Stosuje się je w zależności od tego, co jest dla Ciebie wygodniejsze. Ale o tym opowiem na samym końcu. Najważniejsze jest to, że istnieją trzy narzędzia. Jest z czego wybierać.

Po tym, jak wszystko poprawiliśmy i upewniliśmy się, że wszystko jest w porządku, musimy wiedzieć, jak zapobiec tej sytuacji w przyszłości:

  • Można temu dość łatwo zapobiec. Musisz monitorować czas trwania sesji na serwerze głównym. Szczególnie niebezpieczne sesje w stanie bezczynności w stanie transakcji. To ci, którzy właśnie otworzyli transakcję, zrobili coś i odeszli lub po prostu zawiesili się i zagubili w kodzie.
  • A dla Ciebie, jako programisty, ważne jest testowanie kodu, gdy zaistnieją takie sytuacje. Nie jest to trudne. To będzie przydatna kontrola. Unikniesz dużej liczby „dziecinnych” problemów związanych z długimi transakcjami.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Na tych wykresach chciałem pokazać jak zmienił się znak i zachowanie bazy danych po przejściu przez znak z opcją VACUUM FULL. To nie jest produkcja dla mnie.

Rozmiar tabeli natychmiast powrócił do normalnego stanu operacyjnego wynoszącego kilka megabajtów. Nie wpłynęło to znacząco na średni czas odpowiedzi serwera.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Jednak szczególnie w przypadku naszego znaku testowego, w którym zaktualizowaliśmy salda kont, widzimy, że średni czas odpowiedzi na prośbę o aktualizację danych w znaku został skrócony do poziomu sprzed sytuacji awaryjnych. Zasoby zużywane przez procesor w celu realizacji tego żądania również spadły do ​​poziomu sprzed awarii. A prawy dolny wykres pokazuje, że teraz znajdujemy dokładnie tę linię, której potrzebujemy od razu, bez przechodzenia przez stosy martwych linii, które były tam przed skompresowaniem stołu. A średni czas żądania pozostał na mniej więcej tym samym poziomie. Ale tutaj mam raczej błąd w moim sprzęcie.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

W tym miejscu kończy się pierwsza historia. Jest to najczęstsze. I zdarza się to każdemu, niezależnie od doświadczenia klienta i kwalifikacji programistów. Prędzej czy później to się dzieje.

Druga historia, w której rozkładamy obciążenie i optymalizujemy zasoby serwera

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

  • Już dorośliśmy i staliśmy się poważnymi facetami. I rozumiemy, że mamy replikę i dobrze byłoby, gdybyśmy zrównoważyli obciążenie: napisz do Mistrza i odczytaj z repliki. I zwykle taka sytuacja ma miejsce, gdy chcemy przygotować jakieś raporty lub ETL. Biznes jest z tego bardzo zadowolony. Naprawdę chce różnorodnych raportów z dużą ilością skomplikowanych analiz.
  • Raporty zajmują wiele godzin, ponieważ złożonych analiz nie da się obliczyć w milisekundach. My, jak odważni goście, piszemy kod. W aplikacji wstawiania dokonujemy zapisu na Masterze oraz wykonujemy raporty na replice.
  • Rozłożenie obciążenia.
  • Wszystko działa idealnie. Były świetne.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

A jak wygląda ta sytuacja? Specjalnie na tych wykresach dodałem także czas trwania transakcji z repliki do czasu trwania transakcji. Wszystkie pozostałe wykresy odnoszą się tylko do serwera Master.

Do tego czasu moja tablica raportowa się rozrosła. Jest ich więcej. Widzimy, że średni czas odpowiedzi serwera jest stabilny. Widzimy, że na replice mamy długotrwałą transakcję, która trwa 2 godziny. Widzimy cichą pracę automatycznej próżni, która przetwarza martwe linie. I u nas wszystko w porządku.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

W szczególności, zgodnie z testowaną tabliczką, nadal aktualizujemy tam salda kont. Mamy też stabilny czas reakcji na żądania, stabilne zużycie zasobów. U nas wszystko w porządku.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Wszystko jest w porządku do momentu, gdy raporty zaczną pojawiać się ponownie z powodu konfliktu z replikacją. I strzelają w regularnych odstępach czasu.

Wchodzimy do Internetu i zaczynamy czytać, dlaczego tak się dzieje. I znajdujemy rozwiązanie.

Pierwszym rozwiązaniem jest zwiększenie opóźnienia replikacji. Wiemy, że nasz raport trwa 3 godziny. Ustawiamy opóźnienie replikacji na 3 godziny. Uruchamiamy wszystko, ale nadal mamy problemy z czasami anulowaniem raportów.

Chcemy, żeby wszystko było idealne. Wspinamy się dalej. I znaleźliśmy w Internecie fajne ustawienie - hot_standby_feedback. Włączmy to. Hot_standby_feedback pozwala nam wstrzymać automatyczną próżnię na urządzeniu Master. W ten sposób całkowicie pozbywamy się konfliktów replikacyjnych. I wszystko działa dobrze dla nas z raportami.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

A co się w tym czasie dzieje z serwerem Master? I mamy totalne kłopoty z serwerem Master. Teraz widzimy wykresy, gdy mam włączone oba te ustawienia. I widzimy, że sesja na naszej replice w jakiś sposób zaczęła wpływać na sytuację na serwerze Master. Odniosła skutek, ponieważ wstrzymała automatyczną próżnię, która usuwa martwe linie. Rozmiar naszego stołu ponownie gwałtownie wzrósł. Gwałtownie wzrósł także średni czas wykonywania zapytań w całej bazie danych. Autovacuum trochę się napięło.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Konkretnie z naszego talerza widzimy, że aktualizacja danych na nim również wyskoczyła w przestworza. Podobnie znacznie wzrosło zużycie procesora. Znów przechodzimy przez dużą liczbę martwych, bezużytecznych linii. A czas reakcji na ten znak i liczba transakcji spadły.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Jak to będzie wyglądać, jeśli nie będziemy wiedzieć, o czym mówiłem wcześniej?

  • Zaczynamy szukać problemów. Jeśli w pierwszej części napotkaliśmy problemy, wiemy, że może to być spowodowane długą transakcją i zwracamy się do Mastera. Mamy problem z Mistrzem. Kiełbasy go. Nagrzewa się, jego średnia obciążenia wynosi około stu.
  • Żądania są tam powolne, ale nie widzimy tam żadnych długotrwałych transakcji. I nie rozumiemy o co chodzi. Nie rozumiemy, gdzie szukać.
  • Sprawdzamy sprzęt serwerowy. Może nasz nalot się nie udał. Może nasza pamięć jest spalona. Tak, wszystko może się zdarzyć. Ale nie, serwery są nowe, wszystko działa dobrze.
  • Wszyscy biegają: administratorzy, programiści i dyrektor. Nic nie pomaga.
  • I w pewnym momencie wszystko nagle zaczyna się naprawiać.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

W tym momencie żądanie dotyczące naszej repliki zostało przetworzone i pozostawione. Otrzymaliśmy raport. Biznes jest nadal szczęśliwy. Jak widać nasz znak znów urósł i nie zamierza się kurczyć. Na wykresie z sesjami zostawiłem fragment tej długiej transakcji z repliki, abyście mogli oszacować ile czasu zajmie zanim sytuacja się ustabilizuje.

Sesja dobiegła końca. I dopiero po pewnym czasie serwer przychodzi mniej więcej w porządku. A średni czas odpowiedzi na żądania na serwerze Master wraca do normy. Ponieważ w końcu automatyczna próżnia ma możliwość oczyszczenia i zaznaczenia tych martwych linii. I zaczął wykonywać swoją pracę. I jak szybko to zrobi, tak szybko dojdziemy do porządku.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Według testowanego tabletu, gdzie aktualizujemy salda rachunków, widzimy dokładnie ten sam obraz. Stopniowo normalizuje się także średni czas aktualizacji konta. Zasoby zużywane przez procesor również ulegają zmniejszeniu. A liczba transakcji na sekundę wraca do normy. Ale znowu wracamy do normalności, a nie do tego samego, co przed wypadkiem.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

W każdym razie mamy spadek wydajności, podobnie jak w pierwszym przypadku, półtora do dwóch razy, a czasem więcej.

Wydaje się, że zrobiliśmy wszystko dobrze. Rozłóż ładunek. Sprzęt nie jest bezczynny. Podzieliliśmy prośby według uznania, ale i tak wszystko wyszło źle.

  • Nie włączać funkcji hot_standby_feedback? Tak, nie zaleca się włączania go bez szczególnie ważnych powodów. Ponieważ ten zwrot wpływa bezpośrednio na serwer Master i zawiesza tam działanie autovacuum. Włączając to na jakiejś replice i zapominając o tym, możesz zabić Mistrza i nabawić się dużych problemów z aplikacją.
  • Zwiększyć max_standby_streaming_delay? Tak, jeśli chodzi o raporty, jest to prawdą. Jeśli masz trzygodzinny raport i nie chcesz, aby uległ on awarii z powodu konfliktów replikacji, po prostu zwiększ opóźnienie. Raport długoterminowy nigdy nie wymaga danych, które pojawiły się w bazie danych właśnie teraz. Jeśli masz go przez trzy godziny, oznacza to, że uruchamiasz go przez jakiś stary okres danych. A dla Ciebie to, czy opóźnienie będzie trzygodzinne, czy sześciogodzinne, nie będzie miało żadnego znaczenia, ale raporty będziesz otrzymywać na bieżąco i nie będziesz miał żadnych problemów z ich upadkiem.
  • Naturalnie musisz kontrolować długie sesje na replikach, zwłaszcza jeśli zdecydujesz się włączyć hot_standby_feedback na replice. Ponieważ wszystko może się zdarzyć. Daliśmy tę replikę programiście, aby mógł przetestować zapytania. Napisał szaloną prośbę. Uruchomił go i poszedł napić się herbaty, a my dostaliśmy uznanego Mistrza. A może umieściliśmy tam złą aplikację. Sytuacje są różne. Sesje na replikach muszą być monitorowane równie uważnie, jak na Masterze.
  • A jeśli masz szybkie i długie zapytania dotyczące replik, to w tym przypadku lepiej je podzielić, aby rozłożyć obciążenie. To jest link do streaming_delay. W przypadku szybkich należy mieć jedną replikę z małym opóźnieniem replikacji. W przypadku długotrwałych żądań raportowania należy mieć replikę, która może opóźniać się o 6 godzin lub jeden dzień. Jest to całkowicie normalna sytuacja.

Konsekwencje eliminujemy w ten sam sposób:

  • Znajdujemy nadęte stoły.
  • I kompresujemy go za pomocą najwygodniejszego dla nas narzędzia.

Druga historia kończy się tutaj. Przejdźmy do trzeciej historii.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Również dość powszechne dla nas, w których wykonujemy migrację.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

  • Każde oprogramowanie rozwija się. Wymagania wobec niego zmieniają się. W każdym razie chcemy się rozwijać. A zdarza się, że musimy zaktualizować dane w tabeli, czyli przeprowadzić aktualizację w zakresie naszej migracji pod nową funkcjonalność, którą wprowadzamy w ramach naszego rozwoju.
  • Stary format danych nie jest zadowalający. Powiedzmy, że przechodzimy teraz do drugiej tabeli, w której mam transakcje na tych rachunkach. I powiedzmy, że były w rublach, a my postanowiliśmy zwiększyć dokładność i zrobić to w kopiejkach. I w tym celu musimy dokonać aktualizacji: pomnóż pole z kwotą transakcji przez sto.
  • W dzisiejszym świecie korzystamy z narzędzi automatycznej kontroli wersji baz danych. Powiedzmy Likwibaza. Rejestrujemy tam naszą migrację. Testujemy to na naszej bazie testowej. Wszystko w porządku. Trwa aktualizacja. Blokuje to pracę na jakiś czas, ale otrzymujemy aktualne dane. I możemy uruchomić w tym zakresie nową funkcjonalność. Wszystko zostało przetestowane i sprawdzone. Wszystko zostało potwierdzone.
  • Wykonaliśmy zaplanowane prace i przeprowadziliśmy migrację.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Oto migracja z aktualizacją przedstawioną przed tobą. Ponieważ są to transakcje na moim koncie, płyta miała 15 GB. A ponieważ aktualizujemy każdą linię, dzięki aktualizacji podwoiliśmy rozmiar tabeli, ponieważ przepisaliśmy każdą linię.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Podczas migracji nie mogliśmy nic zrobić z tą płytą, ponieważ wszystkie żądania do niej były kolejkowane i czekały do ​​zakończenia tej aktualizacji. Ale tutaj chcę zwrócić uwagę na liczby znajdujące się na osi pionowej. Oznacza to, że mamy średni czas żądania przed migracją około 5 milisekund, a obciążenie procesora, liczba operacji blokowych odczytu pamięci dyskowej jest mniejsza niż 7,5.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Przeprowadziliśmy migrację i ponownie pojawiły się problemy.

Migracja zakończyła się pomyślnie, ale:

  • Ukończenie starej funkcjonalności zajmuje teraz więcej czasu.
  • Stół znów się powiększył.
  • Obciążenie serwera ponownie stało się większe niż wcześniej.
  • I oczywiście nadal majstrujemy przy funkcjonalności, która działała dobrze, trochę ją ulepszyliśmy.

A to znowu wzdęcia, które znowu rujnują nam życie.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Tutaj pokazuję, że stół, podobnie jak dwa poprzednie przypadki, nie wróci do swoich poprzednich rozmiarów. Średnie obciążenie serwera wydaje się wystarczające.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

A jeśli przejdziemy do tabeli z kontami, zobaczymy, że średni czas żądania dla tej tabeli podwoił się. Obciążenie procesora i liczba uporządkowanych linii w pamięci wzrosła powyżej 7,5, ale była niższa. A w przypadku procesorów podskoczyło 2 razy, w przypadku operacji blokowych 1,5 razy, czyli mamy degradację wydajności serwera. A co za tym idzie – pogorszenie wydajności naszej aplikacji. Jednocześnie liczba połączeń utrzymywała się na mniej więcej tym samym poziomie.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Najważniejsze jest, aby zrozumieć, jak poprawnie wykonać takie migracje. I trzeba je zrobić. Te migracje robimy dość konsekwentnie.

  • Tak duże migracje nie zachodzą automatycznie. Zawsze muszą być pod kontrolą.
  • Wymagany jest nadzór osoby posiadającej wiedzę. Jeśli masz w swoim zespole administratora danych, pozwól mu to zrobić. To jego praca. Jeśli nie, to niech zrobi to najbardziej doświadczona osoba, która wie, jak pracować z bazami danych.
  • Nowy schemat bazy danych, nawet jeśli aktualizujemy jedną kolumnę, zawsze przygotowujemy etapowo, czyli z wyprzedzeniem przed wdrożeniem nowej wersji aplikacji:
  • Dodano nowe pola, w których będziemy zapisywać zaktualizowane dane.
  • Dane ze starego pola przenosimy do nowego w małych fragmentach. Dlaczego to robimy? Po pierwsze, zawsze kontrolujemy przebieg tego procesu. Wiemy, że przekazaliśmy już tak dużo partii, a jeszcze tyle jeszcze nam zostało.
  • A drugi pozytywny efekt jest taki, że pomiędzy każdą taką partią zamykamy transakcję, otwieramy nową, a to pozwala autovacuum pracować zgodnie z płytą, wyznaczamy terminy ostateczne do ponownego użycia.
  • Do linii, które pojawią się w trakcie działania aplikacji (nadal mamy uruchomioną starą aplikację) dodajemy wyzwalacz zapisujący nowe wartości do nowych pól. W naszym przypadku jest to pomnożenie starej wartości przez sto.
  • Jeśli jesteśmy całkowicie uparci i chcemy tego samego pola, to po zakończeniu wszystkich migracji i przed wdrożeniem nowej wersji aplikacji po prostu zmieniamy nazwy pól. Starym nadano jakąś wymyśloną nazwę, a nowym polom zmieniono nazwy na stare.
  • I dopiero potem uruchamiamy nową wersję aplikacji.

A jednocześnie nie dostaniemy wzdęć i nie ucierpimy pod względem wydajności.

W tym miejscu kończy się trzecia historia.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat.sql

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat_approx.sql

A teraz trochę więcej szczegółów na temat narzędzi, o których wspomniałem w pierwszej historii.

Przed wyszukaniem wzdęć musisz zainstalować rozszerzenie pgstattuple.

Abyś nie musiał wymyślać zapytań, napisaliśmy je już w naszej pracy. Możesz z nich skorzystać. Są tu dwie prośby.

  • Pierwszy z nich zajmuje dość dużo czasu, ale pokaże dokładne wartości wzdęć z tabeli.
  • Drugi działa szybciej i jest bardzo skuteczny, gdy trzeba szybko ocenić, czy jest wzdęcie, czy nie, zgodnie z tabelą. Powinieneś także zrozumieć, że w tabeli Postgres zawsze występuje wzdęcie. Jest to cecha modelu MVCC.
  • W większości przypadków wzdęcia o wartości 20% są normalne w przypadku stołów. Oznacza to, że nie powinieneś się martwić i kompresować tego stołu.

Wymyśliliśmy, jak identyfikować tabele wypełnione bezużytecznymi danymi.

Teraz o tym, jak naprawić wzdęcia:

  • Jeśli mamy mały tablet i dobre dyski, czyli na tablecie do gigabajta, całkiem możliwe jest użycie VACUUM FULL. Zabierze od ciebie ekskluzywny zamek na stole na kilka sekund i ok, ale zrobi wszystko szybko i ostro. Co robi VACUUM FULL? Zajmuje wyłączną blokadę stołu i przepisuje aktywne wiersze ze starych tabel do nowej tabeli. A na koniec ich zastępuje. Usuwa stare pliki i zastępuje stare nowymi. Ale na czas swojej pracy zajmuje ekskluzywny zamek na stole. Oznacza to, że nie możesz nic zrobić z tą tabelą: ani pisać do niej, ani czytać jej, ani modyfikować. A VACUUM FULL wymaga dodatkowego miejsca na dysku do zapisu danych.
  • Następne narzędzie pg_repack. W swojej zasadzie jest bardzo podobny do VACUUM FULL, ponieważ dodatkowo przepisuje dane ze starych plików do nowych i podmienia je w tabeli. Ale jednocześnie nie zakłada wyłącznej blokady na stół już na samym początku swojej pracy, lecz podejmuje ją dopiero w momencie, gdy ma już gotowe dane w celu podmiany plików. Wymagania dotyczące zasobów dyskowych są podobne do wymagań VACUUM FULL. Potrzebujesz dodatkowego miejsca na dysku, co czasami ma kluczowe znaczenie, jeśli masz tabele terabajtowe. I jest dość energochłonny, ponieważ aktywnie współpracuje z wejściami/wyjściami.
  • Trzecie narzędzie to pgkompaktowy. Ostrożniej gospodaruje zasobami, bo działa na nieco innych zasadach. Główną ideą pgcompacttable jest to, że przenosi wszystkie aktywne wiersze na początek tabeli za pomocą aktualizacji w tabeli. A następnie uruchamia próżnię na tym stole, ponieważ wiemy, że mamy aktywne wiersze na początku i martwe wiersze na końcu. A sama próżnia odcina ten ogon, czyli nie wymaga dużo dodatkowego miejsca na dysku. Jednocześnie nadal można go ograniczyć pod względem zasobów.

Wszystko z narzędziami.

Typowe błędy w aplikacjach, które prowadzą do wzdęć w postgresql. Andriej Salnikow

Jeśli uważasz, że rozdęty temat jest interesujący pod względem głębszego zagłębienia się w jego treść, oto kilka przydatnych linków:

Starałem się bardziej pokazać horror dla programistów, ponieważ to oni są naszymi bezpośrednimi klientami baz danych i muszą rozumieć, do czego i do czego prowadzą działania. Mam nadzieję, że mi się udało. Dziękuję za uwagę!

pytania

Dziękujemy za raport! Mówiłeś o tym, jak identyfikować problemy. Jak można ich ostrzec? Oznacza to, że miałem sytuację, w której żądania zawieszały się nie tylko z powodu dostępu do niektórych usług zewnętrznych. To były tylko dzikie połączenia. Było kilka drobnych, nieszkodliwych próśb, które wisiały przez jeden dzień, a potem zaczęły robić jakieś bzdury. Czyli bardzo podobnie do tego co opisujesz. Jak to śledzić? Usiądź i stale obserwuj, które żądanie utknęło? Jak można temu zapobiec?

W tym przypadku jest to zadanie dla administratorów Twojej firmy, niekoniecznie dla DBA.

Jestem administratorem.

PostgreSQL ma widok o nazwie pg_stat_activity, który pokazuje wiszące zapytania. I widać jak długo tam wisi.

Czy muszę przychodzić i zaglądać co 5 minut?

Skonfiguruj cron i sprawdź. Jeśli masz długoterminową prośbę, napisz list i tyle. Oznacza to, że nie musisz patrzeć oczami, można to zautomatyzować. Otrzymasz list, zareagujesz na niego. Możesz też strzelać automatycznie.

Czy są jakieś oczywiste powody, dla których tak się dzieje?

Wymieniłem kilka. Inne, bardziej złożone przykłady. I można rozmawiać długo.

Dziękujemy za raport! Chciałem wyjaśnić kwestię narzędzia pg_repack. Jeśli nie zrobi blokady na wyłączność, to...

Robi ekskluzywny zamek.

... wtedy mógłbym potencjalnie stracić dane. Czy moja aplikacja nie powinna w tym czasie nic rejestrować?

Nie, z tabelą działa to płynnie, tzn. pg_repack najpierw przesyła wszystkie istniejące linie na żywo. Naturalnie następuje tam jakiś wpis do tabeli. Po prostu wyrzuca ten kucyk.

To znaczy, że w końcu to robi?

W końcu bierze wyłączną blokadę, aby zamienić te pliki.

Czy będzie szybciej niż VACUUM FULL?

VACUUM FULL, gdy tylko się uruchomił, natychmiast przyjął ekskluzywną blokadę. I dopóki nie zrobi wszystkiego, nie wypuści jej. A pg_repack przyjmuje wyłączną blokadę tylko w momencie wymiany pliku. W tej chwili nie będziesz tam pisać, ale dane nie zostaną utracone, wszystko będzie dobrze.

Cześć! Mówiłeś o działaniu odkurzacza samochodowego. Był tam wykres z czerwonymi, żółtymi i zielonymi komórkami rejestrującymi. Czyli żółte - oznaczył je jako usunięte. I w efekcie da się w nich zapisać coś nowego?

Tak. Postgres nie usuwa linii. Ma taką specyfikę. Jeśli zaktualizowaliśmy linię, oznaczaliśmy starą jako usuniętą. Pojawia się tam identyfikator transakcji, która zmieniła tę linię i piszemy nową linię. Mamy sesje, które potencjalnie mogłyby je odczytać. W pewnym momencie stają się dość stare. Istota działania automatycznej próżni polega na tym, że przechodzi przez te linie i oznacza je jako niepotrzebne. I możesz tam nadpisać dane.

Rozumiem. Ale nie o to chodzi w pytaniu. nie skończyłem. Załóżmy, że mamy stół. Posiada pola o zmiennej wielkości. A jeśli spróbuję wstawić coś nowego, to może po prostu nie zmieścić się w starej komórce.

Nie, w każdym razie cała linia jest tam aktualizowana. Postgres ma dwa modele przechowywania danych. Wybiera typ danych. Istnieją dane przechowywane bezpośrednio w tabeli, ale są też dane tos. Są to duże ilości danych: tekst, json. Są przechowywane na osobnych talerzach. I według tych tabliczek z wzdęciami dzieje się ta sama historia, czyli wszystko jest takie samo. Są po prostu wymienione osobno.

Dziękujemy za raport! Czy dopuszczalne jest używanie zapytań o limit czasu instrukcji w celu ograniczenia czasu trwania?

Bardzo akceptowalne. Używamy tego wszędzie. A ponieważ nie mamy własnych serwisów, zapewniamy wsparcie zdalne, mamy dość różnorodnych klientów. I wszyscy są z tego całkowicie zadowoleni. Oznacza to, że mamy zadania cron, które sprawdzają. Czas trwania sesji jest po prostu uzgadniany z klientem, na co się nie zgadzamy. Może to być minuta, może to być 10 minut. Zależy to od obciążenia podstawy i jej przeznaczenia. Ale wszyscy używamy pg_stat_activity.

Dziękujemy za raport! Próbuję zastosować Twój raport do moich aplikacji. I wygląda na to, że wszędzie zaczynamy transakcję i wszędzie ją wyraźnie kończymy. Jeśli istnieje jakiś wyjątek, wycofywanie nadal następuje. A potem zacząłem myśleć. W końcu transakcja może nie rozpocząć się jawnie. To prawdopodobnie wskazówka dla dziewczyny. Jeśli po prostu zaktualizuję rekord, czy transakcja rozpocznie się w PostgreSQL i zakończy dopiero po rozłączeniu połączenia?

Jeśli mówisz teraz o poziomie aplikacji, to zależy to od używanego sterownika i używanego ORM. Jest tam mnóstwo ustawień. Jeśli masz włączone automatyczne zatwierdzanie, transakcja rozpoczyna się w tym miejscu i zostaje natychmiast zamknięta.

Oznacza to, że zamyka się natychmiast po aktualizacji?

To zależy od ustawień. Nazwałem jedno ustawienie. To jest automatyczne zatwierdzanie włączone. To dość powszechne. Jeśli jest włączona, transakcja została otwarta i zamknięta. Chyba że wyraźnie powiedziałeś „rozpocznij transakcję” i „zakończ transakcję”, ale po prostu uruchomiłeś żądanie w sesji.

Cześć! Dziękujemy za raport! Wyobraźmy sobie, że mamy bazę danych, która puchnie i puchnie, a potem kończy się miejsce na serwerze. Czy są jakieś narzędzia, aby naprawić tę sytuację?

Przestrzeń na serwerze musi być odpowiednio monitorowana.

Na przykład DBA poszedł na herbatę, był w ośrodku itp.

Kiedy tworzony jest system plików, tworzona jest przynajmniej pewna przestrzeń zapasowa, w której nie są zapisywane dane.

A co jeśli będzie całkowicie poniżej zera?

Tam nazywa się to przestrzenią zarezerwowaną, czyli można ją zwolnić i w zależności od tego jak duża została utworzona, otrzymuje się wolne miejsce. Domyślnie nie wiem, ile ich jest. W innym przypadku dostarcz dyski, aby mieć miejsce na operację rekonstrukcyjną. Możesz usunąć tabelę, której na pewno nie będziesz potrzebować.

Czy są jakieś inne narzędzia?

Zawsze jest ręcznie. I lokalnie staje się jasne, co najlepiej tam zrobić, ponieważ niektóre dane są krytyczne, a inne niekrytyczne. A w przypadku każdej bazy danych i aplikacji, która z nią współpracuje, zależy to od firmy. Decyzję zawsze podejmuje się lokalnie.

Dziękujemy za raport! Mam dwa pytania. Najpierw pokazałeś slajdy, które pokazały, że w przypadku zablokowania transakcji zwiększa się zarówno rozmiar obszaru tabel, jak i rozmiar indeksu. W dalszej części raportu znajdowało się kilka narzędzi wchodzących w skład tabletu. A co z indeksem?

Oni też je pakują.

Ale próżnia nie wpływa na indeks?

Niektóre działają z indeksem. Na przykład pg_rapack, pgcompacttable. Próżnia odtwarza indeksy i wpływa na nie. W przypadku VACUUM FULL pomysł jest taki, aby nadpisać wszystko, co oznacza, że ​​działa ze wszystkimi.

I drugie pytanie. Nie rozumiem, dlaczego raporty dotyczące replik tak bardzo zależą od samej replikacji. Wydawało mi się, że raporty się czyta, a replikację zapisuje.

Co powoduje konflikt replikacji? Mamy Mistrza, na którym zachodzą procesy. Trwa odkurzanie samochodu. Do czego właściwie służy odkurzacz automatyczny? Wycina kilka starych linii. Jeżeli w tym momencie mamy żądanie na replikę czytającą te stare linie, a na Masterze zdarzyła się sytuacja, że ​​autovacuum oznaczyło te linie jako możliwe do nadpisania, to je nadpisaliśmy. I otrzymaliśmy pakiet danych, gdy będziemy musieli przepisać te linie, których potrzebuje żądanie w replice, proces replikacji będzie czekał na skonfigurowany limit czasu. A potem PostgreSQL zdecyduje, co jest dla niego ważniejsze. A replikacja jest dla niego ważniejsza niż prośba i będzie strzelał do prośby, aby dokonać tych zmian w replice.

Andriej, mam pytanie. Czy te wspaniałe wykresy, które pokazałeś podczas prezentacji, są efektem pracy jakiejś twojej użyteczności? Jak powstały wykresy?

To jest usługa Okmetr.

Czy jest to produkt komercyjny?

Tak. To jest produkt komercyjny.

Źródło: www.habr.com

Dodaj komentarz