sql >> Database >  >> RDS >> PostgreSQL

Een overzicht van logische replicatie in PostgreSQL

PostgreSQL is een van de meest geavanceerde open source databases ter wereld met veel geweldige functies. Een daarvan is Streaming Replication (Physical Replication) die werd geïntroduceerd in PostgreSQL 9.0. Het is gebaseerd op XLOG-records die worden overgebracht naar de doelserver en daar worden toegepast. Het is echter clustergebaseerd en we kunnen geen enkele database of een enkel object (selectieve replicatie) replicatie uitvoeren. Door de jaren heen zijn we afhankelijk geweest van externe tools zoals Slony, Bucardo, BDR, enz. voor selectieve of gedeeltelijke replicatie, aangezien er geen functie op het kernniveau was tot PostgreSQL 9.6. PostgreSQL 10 kwam echter met een functie genaamd Logische replicatie, waarmee we replicatie op database-/objectniveau kunnen uitvoeren.

Logische replicatie repliceert wijzigingen van objecten op basis van hun replicatie-identiteit, wat meestal een primaire sleutel is. Het is anders dan fysieke replicatie, waarbij replicatie gebaseerd is op blokken en byte-by-byte replicatie. Logische replicatie heeft geen exacte binaire kopie nodig aan de kant van de doelserver, en we hebben de mogelijkheid om op de doelserver te schrijven, in tegenstelling tot fysieke replicatie. Deze functie is afkomstig van de pglogical-module.

In deze blogpost gaan we het hebben over:

  • Hoe het werkt - Architectuur
  • Functies
  • Gebruikssituaties - wanneer het nuttig is
  • Beperkingen
  • Hoe dit te bereiken

Hoe het werkt - Architectuur voor logische replicatie

Logical Replication implementeert een publish en subscribe concept (Publication &Subscription). Hieronder vindt u een architectonisch diagram van een hoger niveau over hoe het werkt.

Basis logische replicatie-architectuur

Publicatie kan worden gedefinieerd op de hoofdserver en het knooppunt waarop het is gedefinieerd, wordt de "uitgever" genoemd. Publicatie is een reeks wijzigingen van een enkele tabel of een groep tabellen. Het is op databaseniveau en elke publicatie bestaat in één database. Aan één publicatie kunnen meerdere tabellen worden toegevoegd en een tabel kan in meerdere publicaties voorkomen. U moet objecten expliciet aan een publicatie toevoegen, behalve als u de optie "ALLE TABELLEN" kiest waarvoor een superuser-privilege vereist is.

U kunt de wijzigingen van objecten (INSERT, UPDATE en DELETE) die moeten worden gerepliceerd, beperken. Standaard worden alle bewerkingstypen gerepliceerd. U moet een replicatie-identiteit hebben geconfigureerd voor het object dat u aan een publicatie wilt toevoegen. Dit is om de UPDATE- en DELETE-bewerkingen te repliceren. De replicatie-identiteit kan een primaire sleutel of een unieke index zijn. Als de tabel geen primaire sleutel of unieke index heeft, kan deze worden ingesteld om de identiteit "volledig" te kopiëren, waarbij alle kolommen als sleutel worden gebruikt (hele rij wordt sleutel).

U kunt een publicatie maken met CREATE PUBLICATION. Enkele praktische commando's worden behandeld in het gedeelte "Hoe dit te bereiken".

Abonnement kan worden gedefinieerd op de doelserver en het knooppunt waarop het is gedefinieerd, wordt de "abonnee" genoemd. De verbinding met de brondatabase wordt gedefinieerd in abonnement. Het abonneeknooppunt is hetzelfde als elke andere stand-alone postgres-database en u kunt het ook gebruiken als publicatie voor verdere abonnementen.

Het abonnement wordt toegevoegd met CREATE ABONNEMENT en kan op elk moment worden gestopt/hervat met de opdracht ALTER ABONNEMENT en verwijderd met DROP ABONNEMENT.

Zodra een abonnement is gemaakt, kopieert Logische replicatie een momentopname van de gegevens in de uitgeversdatabase. Zodra dat is gebeurd, wacht het op deltawijzigingen en stuurt deze naar het abonnementsknooppunt zodra ze zich voordoen.

Hoe worden de wijzigingen echter verzameld? Wie stuurt ze naar het doel? En wie past ze toe op het doelwit? Logische replicatie is ook gebaseerd op dezelfde architectuur als fysieke replicatie. Het wordt geïmplementeerd door "walsender" en "apply" -processen. Aangezien het gebaseerd is op WAL-decodering, wie begint de decodering? Het walsender-proces is verantwoordelijk voor het starten van logische decodering van de WAL en laadt de standaard logische decoderingsplug-in (pgoutput). De plug-in transformeert de gelezen wijzigingen van WAL naar het logische replicatieprotocol en filtert de gegevens volgens de publicatiespecificatie. De gegevens worden vervolgens continu overgedragen met behulp van het streaming-replicatieprotocol naar de toepassingswerker, die de gegevens toewijst aan lokale tabellen en de individuele wijzigingen toepast zodra ze worden ontvangen, in de juiste transactievolgorde.

Het registreert al deze stappen in logbestanden tijdens het instellen. We kunnen de berichten in het gedeelte 'Hoe dit te bereiken' verderop in het bericht zien.

Kenmerken van logische replicatie

  • Logische replicatie repliceert gegevensobjecten op basis van hun replicatie-identiteit (meestal een
  • primaire sleutel of unieke index).
  • Bestemmingsserver kan worden gebruikt voor schrijfbewerkingen. U kunt verschillende indexen en beveiligingsdefinities hebben.
  • Logische replicatie heeft ondersteuning voor meerdere versies. In tegenstelling tot streaming-replicatie, kan logische replicatie worden ingesteld tussen verschillende versies van PostgreSQL (> 9.4 echter)
  • Logische replicatie maakt filtering op basis van gebeurtenissen
  • In vergelijking heeft logische replicatie minder schrijfversterking dan streamingreplicatie
  • Publicaties kunnen meerdere abonnementen hebben
  • Logische replicatie biedt opslagflexibiliteit door het repliceren van kleinere sets (zelfs gepartitioneerde tabellen)
  • Minimale serverbelasting vergeleken met op triggers gebaseerde oplossingen
  • Laat parallelle streaming tussen uitgevers toe
  • Logische replicatie kan worden gebruikt voor migraties en upgrades
  • Gegevenstransformatie kan worden gedaan tijdens het instellen.

Gebruiksscenario's - Wanneer is logische replicatie nuttig?

Het is erg belangrijk om te weten wanneer u logische replicatie moet gebruiken. Anders heb je niet veel voordeel als je use case niet overeenkomt. Dus, hier zijn enkele voorbeelden van wanneer logische replicatie moet worden gebruikt:

  • Als u meerdere databases wilt consolideren in één database voor analytische doeleinden.
  • Als het uw vereiste is om gegevens te repliceren tussen verschillende hoofdversies van PostgreSQL.
  • Als u incrementele wijzigingen in een enkele database of een subset van een database naar andere databases wilt verzenden.
  • Als u toegang geeft tot gerepliceerde gegevens aan verschillende groepen gebruikers.
  • Als een subset van de database wordt gedeeld tussen meerdere databases.

Beperkingen van logische replicatie

Logische replicatie heeft enkele beperkingen waaraan de gemeenschap voortdurend werkt om deze te overwinnen:

  • Tabellen moeten dezelfde volledige naam hebben tussen publicatie en abonnement.
  • Tabellen moeten een primaire sleutel of unieke sleutel hebben
  • Wederzijdse (bidirectionele) replicatie wordt niet ondersteund
  • Repliceert geen schema/DDL
  • Repliceert geen reeksen
  • Repliceert TRUNCATE niet
  • Repliceert geen grote objecten
  • Abonnementen kunnen meer kolommen of een andere volgorde van kolommen hebben, maar de typen en kolomnamen moeten overeenkomen tussen publicatie en abonnement.
  • Superuser-rechten om alle tabellen toe te voegen
  • Je kunt niet naar dezelfde host streamen (abonnement wordt geblokkeerd).
Download de whitepaper vandaag PostgreSQL-beheer en -automatisering met ClusterControlLees wat u moet weten om PostgreSQL te implementeren, bewaken, beheren en schalenDownload de whitepaper

Logische replicatie bereiken

Hier zijn de stappen om basis logische replicatie te bereiken. We kunnen later over complexere scenario's praten.

  1. Initialiseer twee verschillende instanties voor publicatie en abonnement en begin.

    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. Parameters die moeten worden gewijzigd voordat u de instanties start (voor zowel publicatie- als abonnementsinstanties).

    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

    Andere parameters kunnen standaard zijn voor basisinstellingen.

  3. Wijzig het bestand pg_hba.conf om replicatie toe te staan. Houd er rekening mee dat deze waarden afhankelijk zijn van uw omgeving, maar dit is slechts een eenvoudig voorbeeld (voor zowel publicatie- als abonnementsinstanties).

    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. Maak een aantal testtabellen om gegevens te repliceren en in te voegen in de publicatie-instantie.

    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. Creëer een structuur van de tabellen op de Subscription-instantie, aangezien logische replicatie de structuur niet repliceert.

    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. Publicatie maken op publicatie-instantie (poort 5555).

    source_rep=# CREATE PUBLICATION mypub FOR TABLE test_rep, test_rep_other;
    CREATE PUBLICATION
    Time: 3.840 ms
    source_rep=#
  7. Maak een abonnement aan op de abonnementsinstantie (poort 5556) op de publicatie die in stap 6 is gemaakt.

    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

    Uit logboek:

    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

    Zoals u in het NOTICE-bericht kunt zien, heeft het een replicatieslot gecreëerd dat ervoor zorgt dat de WAL-opschoning niet moet worden uitgevoerd voordat de eerste snapshot- of deltawijzigingen zijn overgebracht naar de doeldatabase. Toen begon de WAL-afzender met het decoderen van de wijzigingen, en de toepassing van logische replicatie werkte toen zowel pub als sub werden gestart. Dan start het de tafelsynchronisatie.

  8. Controleer gegevens op abonnementsinstantie.

    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=#

    Zoals u ziet, zijn de gegevens gerepliceerd via de eerste momentopname.

  9. Deltawijzigingen verifiëren.

    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$

Dit zijn de stappen voor een basisconfiguratie van logische replicatie.


  1. Hoe krijg je meerdere tellingen met één SQL-query?

  2. Top 10 redenen waarom u SQL zou moeten leren

  3. Hoe maak je een geneste tabel als database-object in Oracle?

  4. De voordelen van MariaDB's Certified Associate-programma ontsluiten