sql >> Database teknologi >  >> RDS >> PostgreSQL

En oversigt over logisk replikering i PostgreSQL

PostgreSQL er en af ​​de mest avancerede open source-databaser i verden med en masse fantastiske funktioner. En af dem er Streaming Replication (Physical Replication), som blev introduceret i PostgreSQL 9.0. Det er baseret på XLOG-poster, som overføres til destinationsserveren og anvendes der. Det er dog klyngebaseret, og vi kan ikke lave en enkelt database eller enkelt objekt (selektiv replikering) replikering. Gennem årene har vi været afhængige af eksterne værktøjer som Slony, Bucardo, BDR osv. til selektiv eller delvis replikering, da der ikke var nogen funktion på kerneniveauet før PostgreSQL 9.6. PostgreSQL 10 kom dog med en funktion kaldet logisk replikering, hvorigennem vi kan udføre replikering på database-/objektniveau.

Logisk replikering replikerer ændringer af objekter baseret på deres replikeringsidentitet, som normalt er en primær nøgle. Det er anderledes end fysisk replikering, hvor replikering er baseret på blokke og byte-for-byte replikering. Logisk replikering behøver ikke en nøjagtig binær kopi på destinationsserversiden, og vi har mulighed for at skrive på destinationsserveren i modsætning til fysisk replikering. Denne funktion stammer fra det pglogiske modul.

I dette blogindlæg skal vi diskutere:

  • Sådan virker det - Arkitektur
  • Funktioner
  • Brugstilfælde – når det er nyttigt
  • Begrænsninger
  • Sådan opnår du det

Sådan virker det - logisk replikeringsarkitektur

Logisk replikering implementerer et publicerings- og abonnementskoncept (Publication &Subscription). Nedenfor er et arkitektonisk diagram på højere niveau om, hvordan det fungerer.

Grundlæggende logisk replikeringsarkitektur

Udgivelsen kan defineres på masterserveren, og den node, hvorpå den er defineret, omtales som "udgiveren". Udgivelse er et sæt ændringer fra en enkelt tabel eller gruppe af tabeller. Det er på databaseniveau, og hver publikation findes i én database. Flere tabeller kan tilføjes til en enkelt publikation, og en tabel kan være i flere publikationer. Du bør tilføje objekter eksplicit til en publikation, undtagen hvis du vælger "ALLE TABELLER", som kræver et superbrugerprivilegium.

Du kan begrænse ændringerne af objekter (INSERT, UPDATE og DELETE), der skal replikeres. Som standard replikeres alle operationstyper. Du skal have en replikeringsidentitet konfigureret for det objekt, du vil føje til en publikation. Dette er for at replikere OPDATERING og SLET operationer. Replikeringsidentiteten kan være en primær nøgle eller et unikt indeks. Hvis tabellen ikke har en primær nøgle eller et unikt indeks, kan den indstilles til replika-identitet "fuld", hvori den tager alle kolonner som nøgle (hele rækken bliver nøgle).

Du kan oprette en publikation ved at bruge CREATE PUBLICATION. Nogle praktiske kommandoer er dækket i afsnittet "Sådan opnås det".

Abonnementet kan defineres på destinationsserveren, og noden, hvorpå det er defineret, omtales som "abonnenten". Forbindelsen til kildedatabasen er defineret i abonnementet. Abonnentnoden er den samme som enhver anden selvstændig postgres-database, og du kan også bruge den som en publikation til yderligere abonnementer.

Abonnementet tilføjes ved hjælp af CREATE SUBSCRIPTION og kan til enhver tid stoppes/genoptages ved hjælp af kommandoen ALTER SUBSCRIPTION og fjernes ved hjælp af DROP SUBSCRIPTION.

Når et abonnement er oprettet, kopierer logisk replikering et øjebliksbillede af dataene i udgiverdatabasen. Når det er gjort, venter den på deltaændringer og sender dem til abonnementsknuden, så snart de opstår.

Men hvordan indsamles ændringerne? Hvem sender dem til målet? Og hvem anvender dem på målet? Logisk replikering er også baseret på den samme arkitektur som fysisk replikering. Det implementeres af "walsender" og "anvend" processer. Da det er baseret på WAL-afkodning, hvem starter afkodningen? Walsender-processen er ansvarlig for at starte logisk afkodning af WAL og indlæser standard logisk afkodningsplugin (pgoutput). Pluginnet transformerer de læste ændringer fra WAL til den logiske replikeringsprotokol og filtrerer dataene i henhold til publikationsspecifikationen. Dataene overføres derefter kontinuerligt ved hjælp af streaming-replikeringsprotokollen til appliceringsarbejderen, som kortlægger dataene til lokale tabeller og anvender de individuelle ændringer, efterhånden som de modtages, i korrekt transaktionsrækkefølge.

Den logger alle disse trin i logfiler, mens den konfigureres. Vi kan se beskederne i afsnittet "Sådan opnår du det" senere i indlægget.

Funktioner ved logisk replikering

  • Logisk replikering replikerer dataobjekter baseret på deres replikeringsidentitet (generelt en
  • primær nøgle eller unikt indeks).
  • Destinationsserver kan bruges til at skrive. Du kan have forskellige indekser og sikkerhedsdefinitioner.
  • Logisk replikering har understøttelse af flere versioner. I modsætning til streamingreplikering kan logisk replikering indstilles mellem forskellige versioner af PostgreSQL (> 9.4 dog)
  • Logisk replikering udfører hændelsesbaseret filtrering
  • Sammenlignet har logisk replikering mindre skriveforstærkning end streaming replikering
  • Publikationer kan have flere abonnementer
  • Logisk replikering giver lagerfleksibilitet gennem replikering af mindre sæt (selv partitionerede tabeller)
  • Minimum serverbelastning sammenlignet med triggerbaserede løsninger
  • Tillader parallel streaming på tværs af udgivere
  • Logisk replikering kan bruges til migreringer og opgraderinger
  • Datatransformation kan udføres under opsætning.

Use Cases - Hvornår er logisk replikering nyttig?

Det er meget vigtigt at vide, hvornår man skal bruge logisk replikering. Ellers får du ikke meget udbytte, hvis din use case ikke stemmer overens. Så her er nogle eksempler på, hvornår du skal bruge logisk replikering:

  • Hvis du ønsker at konsolidere flere databaser til en enkelt database til analytiske formål.
  • Hvis dit krav er at replikere data mellem forskellige større versioner af PostgreSQL.
  • Hvis du vil sende trinvise ændringer i en enkelt database eller en delmængde af en database til andre databaser.
  • Hvis der gives adgang til replikerede data til forskellige grupper af brugere.
  • Hvis du deler en delmængde af databasen mellem flere databaser.

Begrænsninger af logisk replikering

Logisk replikering har nogle begrænsninger, som fællesskabet løbende arbejder på for at overvinde:

  • Tabeller skal have det samme fulde kvalificerede navn mellem udgivelse og abonnement.
  • Tabeller skal have primær nøgle eller unik nøgle
  • Gensidig (tovejs) replikering understøttes ikke
  • Replikerer ikke skema/DDL
  • Replikerer ikke sekvenser
  • Replikerer ikke TRUNCATE
  • Replikerer ikke store objekter
  • Abonnementer kan have flere kolonner eller en anden rækkefølge af kolonner, men typerne og kolonnenavnene skal matche mellem udgivelse og abonnement.
  • Superbrugerrettigheder til at tilføje alle tabeller
  • Du kan ikke streame over til den samme vært (abonnementet bliver låst).
Download Whitepaper Today PostgreSQL Management &Automation med ClusterControlFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere PostgreSQLDownload Whitepaper

Sådan opnår du logisk replikering

Her er trinene til at opnå grundlæggende logisk replikering. Vi kan diskutere mere komplekse scenarier senere.

  1. Initialiser to forskellige forekomster til udgivelse og abonnement og start.

    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. Parametre, der skal ændres, før du starter forekomsterne (for både udgivelses- og abonnementsforekomster).

    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

    Andre parametre kan være som standard for grundlæggende opsætning.

  3. Skift filen pg_hba.conf for at tillade replikering. Bemærk, at disse værdier afhænger af dit miljø, men dette er kun et grundlæggende eksempel (for både udgivelses- og abonnementsforekomster).

    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. Opret et par testtabeller for at replikere og indsæt nogle data på publikationsforekomsten.

    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. Opret struktur af tabellerne på Subscription-instansen, da logisk replikering ikke replikerer strukturen.

    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. Opret publikation på publikationsinstans (port 5555).

    source_rep=# CREATE PUBLICATION mypub FOR TABLE test_rep, test_rep_other;
    CREATE PUBLICATION
    Time: 3.840 ms
    source_rep=#
  7. Opret abonnement på Subscription-instansen (port 5556) til den publikation, der blev oprettet i trin 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

    Fra log:

    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

    Som du kan se i NOTICE-meddelelsen, oprettede den en replikeringsplads, som sikrer, at WAL-oprydningen ikke bør udføres, før indledende snapshot- eller deltaændringer er overført til måldatabasen. Derefter begyndte WAL-afsenderen at afkode ændringerne, og logisk replikering virkede, da både pub og sub startes. Så starter den tabelsynkroniseringen.

  8. Bekræft data på abonnementsforekomst.

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

    Som du kan se, er data blevet replikeret gennem indledende snapshot.

  9. Bekræft deltaændringer.

    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$

Dette er trinene til en grundlæggende opsætning af logisk replikering.


  1. SQL-udviklerikoner

  2. Datarisikobegrænsning via datamaskering

  3. Undgå Database Vendor Lock-In til MySQL eller MariaDB

  4. Skal jeg oprette en klasse, der arver SQLiteOpenHelper for hver tabel i min database?