„Pro, ale nie klaster” czyli jak wprowadzaliśmy SGBD w Polsce

„Pro, ale nie klaster” czyli jak wprowadzaliśmy SGBD w Polsce
(c) Yandex.Images

Wszystkie postaci są fikcyjne, znaki towarowe należą do ich właścicieli, wszelkie podobieństwa są przypadkowe i w ogóle, to moje „subiektywne osądzenie, proszę nie łamać drzwi…”.

Mamy spore doświadczenie w tłumaczeniu systemów informacyjnych z logiką w bazach danych z jednej SGBD do drugiej. W kontekście rozporządzenia rządu nr 1236 z dnia 16.11.2016, często jest to migracja z Oracle na Postgresql. Jak zorganizować proces maksymalnie efektywnie i bezboleśnie — możemy opowiedzieć osobno, dzisiaj opowiemy o cechach korzystania z klastra i z jakimi problemami można się spotkać przy budowie wysokoobciążonych rozproszonych systemów ze złożoną logiką w procedurach i funkcjach.

SPOILER – tak, kęp RAC i pg multimaster to bardzo różne rozwiązania.

Załóżmy, że już przenieśliście całą logikę z plsql na pgsql. A Wasze testy regresyjne są całkiem OK, teraz oczywiście myślicie o skalowaniu, ponieważ testy obciążeniowe nie napawają Was optymizmem, zwłaszcza na tym sprzęcie, który był założony w projekcie pierwotnie, pod tę inną SGBD. Załóżmy, że znaleźliście rozwiązanie od krajowego dostawcy „Postgres Professional” z opcją o nazwie „multimaster”, która dostępna jest tylko w „maksymalnej” wersji „Postgres Pro Enterprise” i z opisu – to bardzo przypomina to, czego potrzebujecie, a przy pierwszym pobieżnym zapoznaniu się przyjdzie Wam do głowy myśl: „O! Zamiast RAC, to jest to! Oprócz tego z wsparciem technicznym w kraju!”.

Ale nie spieszcie się z radością, dalej opiszemy, dlaczego te niuanse należy znać, ponieważ trudno je przewidzieć, nawet dobrze czytając dokumentację produktu. Oceńcie, czy będziecie gotowi często aktualizować wersje SGBD bezpośrednio na środowisku produkcyjnym, ponieważ niektóre defekty nie są zgodne z eksploatacją przemysłową i trudno je wykryć na testach.
Zacznijcie od uważnego przeczytania sekcji „multimaster” — „ograniczenia” na stronie producenta.

Pierwsze, z czym można się spotkać, to cechy działania transakcji w tzw. „dwufazowym” trybie, a czasami, poza przepisaniem całej logiki Waszej procedury, nie da się tego w żaden sposób poprawić. Oto prosty przykład:

stwórz tabelę test1 (id integer, id1 integer);
wstaw do test1 wartości (1, 1),(1, 2);
 
ALTER TABLE test1 DODAJ KONSTRUKCJĘ test1_uk UNIKALNY (id,id1) ODWLEKALNY POCZĄTKOWO ODWLECZONY;
 
aktualizuj test1
           ustaw id1 =
               przypadku id1
                 gdy 1
                 wtedy 2
                 w przeciwnym razie id1 - znak(2 - 1)
               koniec
         gdzie id1 jest między 1 a 2;

Pojawia się błąd:

BŁĄD:  [MTM] Transakcja MTM-1-2435-10-605783555137701 (10654) została przerwana na węźle 3. Sprawdź jego dziennik, aby zobaczyć szczegóły błędu.

Można długo zmagać się z zablokowaniem w wersjach 10.5, 10.6, a jedynym znanym ratunkiem, który zabija cały sens klastra, jest usunięcie z klastra "problemowych" tabel, tzn. zrobienie make_table_local, ale przynajmniej to pozwoli na pracę, a nie postawi wszystko "w martwym punkcie" z powodu zawieszonych oczekiwań na zatwierdzenie transakcji. Albo aktualizować do wersji 11.2, która powinna pomóc, a może nie, nie zapomnij sprawdzić.

W niektórych wersjach możesz napotkać jeszcze dziwniejsze zablokowanie:

username= mtm i backend_type = background worker

A w tej sytuacji pomoże Ci tylko aktualizacja wersji DBMS do 11.2 i wyżej, a może i nie pomoże.

Niektóre operacje z indeksami mogą prowadzić do błędów, w których wyraźnie wskazano, że problem dotyczy Bi-Directional Replication, w logach MTM zobaczysz bezpośrednio BDR. Naprawdę 2ndQuadrant? Nie… kupiliśmy multimaster, to tylko przypadek, to nazwa technologii.

[MTM] bdr nie obsługuje re-checków indeksów
[MTM] 12124: ZDALNE rozpoczęcie przerwania transakcji 4083
[MTM] 12124: wysyłanie powiadomienia ABORT dla transakcji (5467) lokalny xid=4083 do koordynatora 3
[MTM] Odebrano ABORT_PREPARED komunikat logiczny dla transakcji MTM-3-25030-83-605694076627780 z węzła 3
[MTM] Wstrzymaj przygotowaną transakcję MTM-3-25030-83-605694076627780 status InProgress z węzła 3 originId=3
[MTM] MtmLogAbortLogicalMessage node=3 transaction=MTM-3-25030-83-605694076627780 lsn=9fff448 

Jeśli używasz tymczasowych tabel, mimo zapewnień: „Rozszerzenie multimaster dokonuje replikacji danych w sposób w pełni automatyczny. Możesz jednocześnie wykonywać operacje zapisu i pracować z tymczasowymi tabelami na dowolnym węźle klastra”.

Wtedy w rzeczywistości otrzymasz, że replikacja nie działa dla wszystkich tabel używanych w procedurze, jeśli w kodzie istnieje tworzenie tymczasowej tabeli, a nawet użycie multimaster.remote_functions nie pomoże, będziesz musiał zaktualizować lub przepisać swoją logikę w procedurze. Jeśli musisz jednocześnie używać dwóch rozszerzeń multimaster i pg_pathman w ramach „Postgres Pro Enterprise” v 10.5, upewnij się, że przy takim prostym przykładzie:

UTWÓRZ TABELĘ measurement (
    city_id         int NOT NULL,
    logdate         date NOT NULL,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

UTWÓRZ TABELĘ measurement_y2019m06 PARTITION OF measurement FOR VALUES FROM ('2019-06-01') TO ('2019-07-01');
INSERT INTO measurement VALUES (1, TO_DATE('27.06.2019', 'dd.mm.yyyy'), 1, 1);
INSERT INTO measurement VALUES (2, TO_DATE('28.06.2019', 'dd.mm.yyyy'), 1, 1);
INSERT INTO measurement VALUES (3, TO_DATE('29.06.2019', 'dd.mm.yyyy'), 1, 1);
INSERT INTO measurement VALUES (4, TO_DATE('30.06.2019', 'dd.mm.yyyy'), 1, 1);

W logach na węzłach DBMS zaczynają pojawiać się takie błędy:

…
 PATHMAN_CONFIG nie zawiera relacji 23245
> find_in_dynamic_libpath: próba "\/opt\/…\/ent-10\/lib\/pg_pathman"
> find_in_dynamic_libpath: próba "\/opt\/…\/ent-10\/lib\/pg_pathman.so"
> DEBAGOWANIE: find_in_dynamic_libpath: próba "\/opt\/…\/ent-10\/lib\/pg_pathman"
> find_in_dynamic_libpath: próba "\/opt\/…\/ent-10\/lib\/pg_pathman.so"
> PrepareTransaction(1) nazwa: unnamed; blockState: PREPARE; stan: INPROGR, xid/subid/cid: 6919/1/40
> StartTransaction(1) nazwa: unnamed; blockState: DEFAULT; stan: INPROGR, xid/subid/cid: 0/1/0
> przełączono na linię czasu 1 aktywna aż do 0/0
…
Transakcja MTM-1-13604-7-612438856339841 (6919) została przerwana na węźle 2. Sprawdź jego log, aby zobaczyć szczegóły błędów.
...
[MTM] 28295: REMOTE begin abort transaction 7017
…
[MTM] 28295: wysyłanie powiadomienia ABORT dla transakcji (6919) lokalny xid=7017 do koordynatora 1

Jakie to błędy, dowiesz się w dziale wsparcia technicznego, nie bez powodu go kupiłeś.

Co robić? Oczywiście! Zaktualizować do "Postgres Pro Enterprise" do wersji 11.2

Należy wiedzieć, że sekwencja, jako obiekt repliki DB, nie ma wartości globalnej w klastrze, każda sekwencja jest lokalna dla każdego węzła i jeśli masz pola z unikalnymi ograniczeniami, które używają sekwencji, możesz tylko zrobić inkrementację równą numerowi węzła w klastrze, ponieważ liczba węzłów w klastrze przyspieszy wzrost sekwencji, a int skończy się szybciej niż się spodziewałeś. Dla uproszczenia pracy z sekwencjami w produkcie znajdziesz funkcję alter_sequences, która zrobi odpowiednie inkrementy dla każdej sekwencji na wszystkich węzłach, ale bądź gotowy, że funkcja nie będzie działać we wszystkich wersjach. Oczywiście możesz ją napisać samodzielnie, bazując na kodzie z githuba lub poprawiając go bezpośrednio w DBMS. Przy tym pola o typie serial/bigserial będą działać bardziej poprawnie, ale prawdopodobnie będziesz musiał przepisać kod swoich procedur i funkcji. Może to być pomocne dla kogoś funkcja monotonic_sequences.

Do wersji 11.2 "Postgres Pro Enterprise" replikacja będzie działać tylko przy posiadaniu unikalnych kluczy głównych, weź to pod uwagę przy projektowaniu.

Osobno chciałbym wspomnieć o szczególnych właściwościach działania npgsql w rozwiązaniach klastrowych; te problemy nie występują na pojedynczym węźle, ale w multi-masterze są obecne.
W niektórych wersjach można napotkać błąd:

Szczegóły wyjątku: Npgsql.PostgresException: 25001: polecenie SET TRANSACTION ISOLATION LEVEL 
Opis: Wystąpił nieobsłużony wyjątek podczas wykonywania aktualnego żądania webowego. Proszę zapoznać się z trasą stosu, aby uzyskać więcej informacji o błędzie i miejscu, w którym powstał w kodzie. 

Co można zrobić? Po prostu nie używać niektórych wersji. Należy je znać, ponieważ błąd nie występuje w jednej wersji, a nawet po jej pierwszym poprawieniu można się z nim spotkać później. Na to również trzeba być gotowym, a wszystkie wykryte wady systemów DB, które poprawia producent, należy przykrywać osobnymi testami regresyjnymi. Można powiedzieć: ufaj, ale sprawdzaj.

Jeśli aplikacja korzysta z npgsql i przełącza się między węzłami, myśląc, że są one po prostu takie same, może pojawić się błąd:

WYJĄTEK: Npgsql.PostgresException (0x80004005): XX000: błąd wyszukiwania pamięci podręcznej dla typu ...

Taki błąd wystąpi w wyniku realizacji związania

(NpgsqlConnection.GlobalTypeMapper.MapComposite("some_composite_type");) 

kompozytowych typów podczas uruchamiania aplikacji dla wszystkich połączeń. W efekcie otrzymujemy identyfikator z jednego węzła, a przy zapytaniu do innego węzła nie zgadza się, w wyniku czego zwracany jest błąd, tzn. przejrzysta praca z typami kompozytowymi w klastrze dla niektórych aplikacji będzie niemożliwa bez dodatkowych przepisów po stronie aplikacji (jeśli uda się to zrobić).

Jak wszyscy wiemy, ogólna ocena stanu klastra jest bardzo ważna dla diagnostyki i działań operacyjnych w pracy; w produkcie znajdziesz pewne funkcje, które powinny ułatwiać Ci życie, ale czasami mogą one wydawać zupełnie nie to, czego się spodziewasz, a nawet sam producent.

Na przykład:

select mtm.collect_cluster_info();
na każdym węźle zwraca ten sam wynik:
(1,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:06")
(2,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:06")
(3,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:09")

Ale dlaczego w polu LiveNodes wszędzie stoi liczba 2, chociaż zgodnie z opisem pracy multi-mastera powinna odpowiadać liczbie AllNodes=3? Odpowiedź: należy zaktualizować wersję DB.

Bądź gotowy do zbierania logów ze wszystkich węzłów, ponieważ zwykle zobaczysz "błąd znajduje się w logu innego węzła". Wsparcie techniczne przyjmie wszystkie zgłoszone przez ciebie błędy i poinformuje o gotowości kolejnej wersji, którą czasami będzie trzeba zainstalować z zatrzymaniem usługi, a czasami na długo (zależy to od wielkości twojej bazy danych). Nie należy liczyć na to, że problemy eksploatacyjne będą szczególnie niepokoić dostawcę, a aktualizacja z powodu zgłoszonych błędów będzie przeprowadzana przy udziale przedstawicieli dostawcy, a wręcz nie należy angażować przedstawicieli dostawcy, ponieważ w rezultacie możesz mieć w produkcji rozebrany klaster bez kopii zapasowej.

W samej licencji na komercyjny produkt producent szczerze ostrzega: "To oprogramowanie jest dostarczane na zasadzie "jak jest" i spółka z o.o. "Postgres Profesjonalny" nie ma obowiązku zapewnienia wsparcia, obsługi, aktualizacji, rozszerzeń ani zmian."

Jeśli jeszcze nie domyśliłeś się, o jaki produkt chodzi, to całe to doświadczenie zostało zdobyte w wyniku rocznej eksploatacji bazy Postgres Pro Enterprise. Możesz wyciągnąć samodzielne wnioski, taka to surowość, że grzyby rosną.

Ale to jeszcze byłoby pół biedy, gdyby problemy były eliminowane w odpowiednim czasie i szybko.

Ale tego właśnie nie ma. Najwyraźniej producent nie ma wystarczających zasobów, aby szybko usuwać zgłoszone błędy.

Tylko zarejestrowani użytkownicy mogą brać udział w ankiecie. Zaloguj się, proszę.

Czy masz doświadczenie w migracji z zagranicznej/proprietarnej bazy danych na wolną/krajową?

  • 21,3%Tak, pozytywne10

  • 10,6%Tak, negatywne5

  • 21,3%Nie, nie zmienialiśmy bazy danych10

  • 4,3%Zmienialiśmy bazę danych, ale nic się nie zmieniło2

  • 42,6%Zobacz wyniki20

Głosowało 47 użytkowników. Wstrzymało się 12 użytkowników.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster