PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przegląd replikacji logicznej w PostgreSQL

PostgreSQL to jedna z najbardziej zaawansowanych baz danych open source na świecie z wieloma wspaniałymi funkcjami. Jednym z nich jest replikacja strumieniowa (replikacja fizyczna), która została wprowadzona w PostgreSQL 9.0. Opiera się na rekordach XLOG, które są przesyłane na serwer docelowy i tam stosowane. Jest jednak oparty na klastrach i nie możemy wykonać replikacji pojedynczej bazy danych lub pojedynczego obiektu (replikacja selektywna). Przez lata byliśmy zależni od zewnętrznych narzędzi, takich jak Slony, Bucardo, BDR, itp. do selektywnej lub częściowej replikacji, ponieważ nie było żadnej funkcji na poziomie rdzenia aż do PostgreSQL 9.6. Jednak PostgreSQL 10 wymyślił funkcję o nazwie Logiczna replikacja, dzięki której możemy wykonać replikację na poziomie bazy danych/obiektu.

Replikacja logiczna replikuje zmiany obiektów na podstawie ich tożsamości replikacji, która zwykle jest kluczem podstawowym. Różni się od replikacji fizycznej, w której replikacja opiera się na blokach i replikacji bajt po bajcie. Replikacja logiczna nie wymaga dokładnej kopii binarnej po stronie serwera docelowego, a w przeciwieństwie do replikacji fizycznej mamy możliwość pisania na serwerze docelowym. Ta funkcja pochodzi z modułu pglogical.

W tym poście na blogu omówimy:

  • Jak to działa — architektura
  • Funkcje
  • Przypadki użycia – kiedy jest to przydatne
  • Ograniczenia
  • Jak to osiągnąć

Jak to działa — architektura replikacji logicznej

Logiczna replikacja implementuje koncepcję publikowania i subskrybowania (publikacja i subskrypcja). Poniżej znajduje się diagram architektury wyższego poziomu przedstawiający, jak to działa.

Podstawowa architektura replikacji logicznej

Publikację można zdefiniować na serwerze głównym, a węzeł, w którym jest zdefiniowana, jest określany jako „wydawca”. Publikacja to zbiór zmian z pojedynczej tabeli lub grupy tabel. Odbywa się to na poziomie bazy danych, a każda publikacja istnieje w jednej bazie danych. Do jednej publikacji można dodać wiele tabel, a tabela może znajdować się w wielu publikacjach. Powinieneś dodawać obiekty bezpośrednio do publikacji, chyba że wybierzesz opcję „WSZYSTKIE TABLICE”, która wymaga uprawnień superużytkownika.

Możesz ograniczyć zmiany obiektów (WSTAW, AKTUALIZUJ i USUŃ), które mają być replikowane. Domyślnie replikowane są wszystkie typy operacji. Musisz mieć skonfigurowaną tożsamość replikacji dla obiektu, który chcesz dodać do publikacji. Ma to na celu replikację operacji UPDATE i DELETE. Tożsamość replikacji może być kluczem podstawowym lub unikalnym indeksem. Jeśli tabela nie ma klucza podstawowego ani unikalnego indeksu, można ją ustawić na replikę tożsamości „pełną”, w której wszystkie kolumny są traktowane jako klucz (cały wiersz staje się kluczem).

Publikację można utworzyć za pomocą opcji UTWÓRZ PUBLIKACJĘ. Niektóre praktyczne polecenia opisano w sekcji „Jak to osiągnąć”.

Subskrypcję można zdefiniować na serwerze docelowym, a węzeł, na którym jest zdefiniowana, jest określany jako „subskrybent”. Połączenie do źródłowej bazy danych jest zdefiniowane w abonamencie. Węzeł subskrybenta jest taki sam, jak każda inna samodzielna baza danych Postgres i możesz go również użyć jako publikacji do dalszych subskrypcji.

Subskrypcja jest dodawana za pomocą CREATE SUBSCRIPTION i może być zatrzymana/wznowiona w dowolnym momencie za pomocą polecenia ALTER SUBSCRIPTION i usunięta za pomocą DROP SUBSCRIPTION.

Po utworzeniu subskrypcji replikacja logiczna kopiuje migawkę danych w bazie danych wydawcy. Po wykonaniu tej czynności czeka na zmiany delta i wysyła je do węzła subskrypcji, gdy tylko się pojawią.

Jak jednak zbierane są zmiany? Kto wysyła je do celu? A kto stosuje je u celu? Replikacja logiczna jest również oparta na tej samej architekturze, co replikacja fizyczna. Jest realizowany przez procesy „walsender” i „apply”. Ponieważ opiera się na dekodowaniu WAL, kto rozpoczyna dekodowanie? Proces walsendera jest odpowiedzialny za rozpoczęcie logicznego dekodowania WAL i ładowanie standardowej wtyczki dekodowania logicznego (pgoutput). Wtyczka przekształca zmiany odczytane z WAL na protokół replikacji logicznej i filtruje dane zgodnie ze specyfikacją publikacji. Dane są następnie w sposób ciągły przesyłane za pomocą protokołu replikacji strumieniowej do procesu roboczego aplikacji, który mapuje dane do lokalnych tabel i stosuje poszczególne zmiany w miarę ich odbierania, we właściwej kolejności transakcyjnej.

Rejestruje wszystkie te kroki w plikach dziennika podczas konfigurowania. W dalszej części wpisu możemy zobaczyć komunikaty w sekcji „Jak to osiągnąć”.

Funkcje replikacji logicznej

  • Replikacja logiczna replikuje obiekty danych na podstawie ich tożsamości replikacji (zazwyczaj
  • klucz podstawowy lub unikalny indeks).
  • Do zapisów można używać serwera docelowego. Możesz mieć różne indeksy i definicje bezpieczeństwa.
  • Replikacja logiczna obsługuje wiele wersji. W przeciwieństwie do replikacji strumieniowej, replikację logiczną można ustawić między różnymi wersjami PostgreSQL (> 9.4)
  • Replikacja logiczna wykonuje filtrowanie oparte na zdarzeniach
  • W porównaniu, replikacja logiczna ma mniejsze wzmocnienie zapisu niż replikacja strumieniowa
  • Publikacje mogą mieć kilka subskrypcji
  • Replikacja logiczna zapewnia elastyczność przechowywania poprzez replikowanie mniejszych zestawów (nawet partycjonowanych tabel)
  • Minimalne obciążenie serwera w porównaniu z rozwiązaniami opartymi na wyzwalaczach
  • Pozwala na równoległe przesyłanie strumieniowe między wydawcami
  • Replikacja logiczna może być używana do migracji i aktualizacji
  • Transformację danych można przeprowadzić podczas konfiguracji.

Przypadki użycia — kiedy replikacja logiczna jest przydatna?

Bardzo ważne jest, aby wiedzieć, kiedy używać replikacji logicznej. W przeciwnym razie nie odniesiesz większych korzyści, jeśli Twój przypadek użycia nie będzie pasował. Oto kilka przypadków użycia, w których należy użyć replikacji logicznej:

  • Jeśli chcesz skonsolidować wiele baz danych w jedną bazę danych do celów analitycznych.
  • Jeśli Twoim wymaganiem jest replikacja danych między różnymi głównymi wersjami PostgreSQL.
  • Jeśli chcesz wysyłać zmiany przyrostowe w pojedynczej bazie danych lub podzbiorze bazy danych do innych baz danych.
  • Jeśli dajesz dostęp do zreplikowanych danych różnym grupom użytkowników.
  • Jeśli dzielisz podzbiór bazy danych między wieloma bazami danych.

Ograniczenia replikacji logicznej

Logiczna replikacja ma pewne ograniczenia, nad którymi społeczność nieustannie pracuje, aby przezwyciężyć:

  • Tabele muszą mieć taką samą pełną kwalifikowaną nazwę między publikacją a subskrypcją.
  • Tabele muszą mieć klucz podstawowy lub klucz unikalny
  • Wzajemna (dwukierunkowa) replikacja nie jest obsługiwana
  • Nie replikuje schematu/DDL
  • Nie replikuje sekwencji
  • Nie replikuje OBCIĄŻAJ
  • Nie replikuje dużych obiektów
  • Subskrypcje mogą mieć więcej kolumn lub inną kolejność kolumn, ale typy i nazwy kolumn muszą być zgodne między publikacją a subskrypcją.
  • Uprawnienia superużytkownika do dodawania wszystkich tabel
  • Nie możesz przesyłać strumieniowo do tego samego hosta (subskrypcja zostanie zablokowana).
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 dokument

Jak osiągnąć replikację logiczną

Oto kroki do osiągnięcia podstawowej replikacji logicznej. O bardziej złożonych scenariuszach możemy omówić później.

  1. Zainicjuj dwie różne instancje publikacji i subskrypcji i rozpocznij.

    C1MQV0FZDTY3:bin bajishaik$ export PATH=$PWD:$PATH
    C1MQV0FZDTY3:bin bajishaik$ which psql
    /Users/bajishaik/pg_software/10.2/bin/psql
    C1MQV0FZDTY3:bin bajishaik$ ./initdb -D /tmp/publication_db
    
    C1MQV0FZDTY3:bin bajishaik$ ./initdb -D /tmp/subscription_db
  2. Parametry, które należy zmienić przed uruchomieniem instancji (zarówno dla instancji publikacji, jak i subskrypcji).

    C1MQV0FZDTY3:bin bajishaik$ tail -3 /tmp/publication_db/postgresql.conf
    listen_addresses='*'
    port = 5555
    wal_level= logical
    
    
    C1MQV0FZDTY3:bin bajishaik$ pg_ctl -D /tmp/publication_db/ start
    waiting for server to start....2018-03-21 16:03:30.394 IST [24344] LOG:  listening on IPv4 address "0.0.0.0", port 5555
    2018-03-21 16:03:30.395 IST [24344] LOG:  listening on IPv6 address "::", port 5555
    2018-03-21 16:03:30.544 IST [24344] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5555"
    2018-03-21 16:03:30.662 IST [24345] LOG:  database system was shut down at 2018-03-21 16:03:27 IST
    2018-03-21 16:03:30.677 IST [24344] LOG:  database system is ready to accept connections
     done
    server started
    
    C1MQV0FZDTY3:bin bajishaik$ tail -3 /tmp/subscription_db/postgresql.conf
    listen_addresses='*'
    port=5556
    wal_level=logical
    
    C1MQV0FZDTY3:bin bajishaik$ pg_ctl -D /tmp/subscription_db/ start
    waiting for server to start....2018-03-21 16:05:28.408 IST [24387] LOG:  listening on IPv4 address "0.0.0.0", port 5556
    2018-03-21 16:05:28.408 IST [24387] LOG:  listening on IPv6 address "::", port 5556
    2018-03-21 16:05:28.410 IST [24387] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5556"
    2018-03-21 16:05:28.460 IST [24388] LOG:  database system was shut down at 2018-03-21 15:59:32 IST
    2018-03-21 16:05:28.512 IST [24387] LOG:  database system is ready to accept connections
     done
    server started

    Inne parametry mogą być ustawione jako domyślne dla podstawowej konfiguracji.

  3. Zmień plik pg_hba.conf, aby umożliwić replikację. Pamiętaj, że te wartości są zależne od Twojego środowiska, jednak jest to tylko podstawowy przykład (zarówno dla instancji publikacji, jak i subskrypcji).

    C1MQV0FZDTY3:bin bajishaik$ tail -1 /tmp/publication_db/pg_hba.conf
     host     all     repuser     0.0.0.0/0     md5
    C1MQV0FZDTY3:bin bajishaik$ tail -1 /tmp/subscription_db/pg_hba.conf
     host     all     repuser     0.0.0.0/0     md5
    
    C1MQV0FZDTY3:bin bajishaik$ psql -p 5555 -U bajishaik -c "select pg_reload_conf()"
    Timing is on.
    Pager usage is off.
    2018-03-21 16:08:19.271 IST [24344] LOG:  received SIGHUP, reloading configuration files
     pg_reload_conf
    ----------------
     t
    (1 row)
    
    Time: 16.103 ms
    C1MQV0FZDTY3:bin bajishaik$ psql -p 5556 -U bajishaik -c "select pg_reload_conf()"
    Timing is on.
    Pager usage is off.
    2018-03-21 16:08:29.929 IST [24387] LOG:  received SIGHUP, reloading configuration files
     pg_reload_conf
    ----------------
     t
    (1 row)
    
    Time: 53.542 ms
    C1MQV0FZDTY3:bin bajishaik$
  4. Utwórz kilka tabel testowych, aby zreplikować i wstawić niektóre dane do instancji publikacji.

    postgres=# create database source_rep;
    CREATE DATABASE
    Time: 662.342 ms
    postgres=# \c source_rep
    You are now connected to database "source_rep" as user "bajishaik".
    source_rep=# create table test_rep(id int primary key, name varchar);
    CREATE TABLE
    Time: 63.706 ms
    source_rep=# create table test_rep_other(id int primary key, name varchar);
    CREATE TABLE
    Time: 65.187 ms
    source_rep=# insert into test_rep values(generate_series(1,100),'data'||generate_series(1,100));
    INSERT 0 100
    Time: 2.679 ms
    source_rep=# insert into test_rep_other  values(generate_series(1,100),'data'||generate_series(1,100));
    INSERT 0 100
    Time: 1.848 ms
    source_rep=# select count(1) from test_rep;
     count
    -------
       100
    (1 row)
    
    Time: 0.513 ms
    source_rep=# select count(1) from test_rep_other ;
     count
    -------
       100
    (1 row)
    
    Time: 0.488 ms
    source_rep=#
  5. Utwórz strukturę tabel w instancji subskrypcji, ponieważ replikacja logiczna nie replikuje struktury.

    postgres=# create database target_rep;
    CREATE DATABASE
    Time: 514.308 ms
    postgres=# \c target_rep
    You are now connected to database "target_rep" as user "bajishaik".
    target_rep=# create table test_rep_other(id int primary key, name varchar);
    CREATE TABLE
    Time: 9.684 ms
    target_rep=# create table test_rep(id int primary key, name varchar);
    CREATE TABLE
    Time: 5.374 ms
    target_rep=#
  6. Utwórz publikację na instancji publikacji (port 5555).

    source_rep=# CREATE PUBLICATION mypub FOR TABLE test_rep, test_rep_other;
    CREATE PUBLICATION
    Time: 3.840 ms
    source_rep=#
  7. Utwórz subskrypcję na instancji subskrypcji (port 5556) do publikacji utworzonej w kroku 6.

    target_rep=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=source_rep host=localhost user=bajishaik port=5555' PUBLICATION mypub;
    NOTICE:  created replication slot "mysub" on publisher
    CREATE SUBSCRIPTION
    Time: 81.729 ms

    Z dziennika:

    2018-03-21 16:16:42.200 IST [24617] LOG:  logical decoding found consistent point at 0/1616D80
    2018-03-21 16:16:42.200 IST [24617] DETAIL:  There are no running transactions.
    target_rep=# 2018-03-21 16:16:42.207 IST [24618] LOG:  logical replication apply worker for subscription "mysub" has started
    2018-03-21 16:16:42.217 IST [24619] LOG:  starting logical decoding for slot "mysub"
    2018-03-21 16:16:42.217 IST [24619] DETAIL:  streaming transactions committing after 0/1616DB8, reading WAL from 0/1616D80
    2018-03-21 16:16:42.217 IST [24619] LOG:  logical decoding found consistent point at 0/1616D80
    2018-03-21 16:16:42.217 IST [24619] DETAIL:  There are no running transactions.
    2018-03-21 16:16:42.219 IST [24620] LOG:  logical replication table synchronization worker for subscription "mysub", table "test_rep" has started
    2018-03-21 16:16:42.231 IST [24622] LOG:  logical replication table synchronization worker for subscription "mysub", table "test_rep_other" has started
    2018-03-21 16:16:42.260 IST [24621] LOG:  logical decoding found consistent point at 0/1616DB8
    2018-03-21 16:16:42.260 IST [24621] DETAIL:  There are no running transactions.
    2018-03-21 16:16:42.267 IST [24623] LOG:  logical decoding found consistent point at 0/1616DF0
    2018-03-21 16:16:42.267 IST [24623] DETAIL:  There are no running transactions.
    2018-03-21 16:16:42.304 IST [24621] LOG:  starting logical decoding for slot "mysub_16403_sync_16393"
    2018-03-21 16:16:42.304 IST [24621] DETAIL:  streaming transactions committing after 0/1616DF0, reading WAL from 0/1616DB8
    2018-03-21 16:16:42.304 IST [24621] LOG:  logical decoding found consistent point at 0/1616DB8
    2018-03-21 16:16:42.304 IST [24621] DETAIL:  There are no running transactions.
    2018-03-21 16:16:42.306 IST [24620] LOG:  logical replication table synchronization worker for subscription "mysub", table "test_rep" has finished
    2018-03-21 16:16:42.308 IST [24622] LOG:  logical replication table synchronization worker for subscription "mysub", table "test_rep_other" has finished

    Jak widać w komunikacie NOTICE, utworzono szczelinę replikacji, która zapewnia, że ​​czyszczenie WAL nie powinno zostać wykonane, dopóki początkowe zmiany migawki lub delta nie zostaną przesłane do docelowej bazy danych. Następnie nadawca WAL rozpoczął dekodowanie zmian, a zastosowanie replikacji logicznej zadziałało, gdy uruchomiono zarówno pub, jak i sub. Następnie rozpoczyna synchronizację tabeli.

  8. Zweryfikuj dane w instancji subskrypcji.

    target_rep=# select count(1) from test_rep;
     count
    -------
       100
    (1 row)
    
    Time: 0.927 ms
    target_rep=# select count(1) from test_rep_other ;
     count
    -------
       100
    (1 row)
    
    Time: 0.767 ms
    target_rep=#

    Jak widzisz, dane zostały zreplikowane przez początkowy zrzut.

  9. Sprawdź zmiany delta.

    C1MQV0FZDTY3:bin bajishaik$ psql -d postgres -p 5555 -d source_rep -c "insert into test_rep values(generate_series(101,200), 'data'||generate_series(101,200))"
    INSERT 0 100
    Time: 3.869 ms
    C1MQV0FZDTY3:bin bajishaik$ psql -d postgres -p 5555 -d source_rep -c "insert into test_rep_other values(generate_series(101,200), 'data'||generate_series(101,200))"
    INSERT 0 100
    Time: 3.211 ms
    C1MQV0FZDTY3:bin bajishaik$ psql -d postgres -p 5556 -d target_rep -c "select count(1) from test_rep"
     count
    -------
       200
    (1 row)
    
    Time: 1.742 ms
    C1MQV0FZDTY3:bin bajishaik$ psql -d postgres -p 5556 -d target_rep -c "select count(1) from test_rep_other"
     count
    -------
       200
    (1 row)
    
    Time: 1.480 ms
    C1MQV0FZDTY3:bin bajishaik$

Oto kroki podstawowej konfiguracji replikacji logicznej.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dodanie kolumny jako klucza obcego powoduje, że kolumna ERROR, do której odwołuje się ograniczenie klucza obcego, nie istnieje

  2. Heroku Rails 4 nie może połączyć się z serwerem:połączenie odrzucone

  3. Czy istnieje sposób na wyłączenie przeciążania funkcji w Postgresie?

  4. O indeksie klastrowym w postgres

  5. Jak używać pgBackRest do tworzenia kopii zapasowych PostgreSQL i TimescaleDB?