PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Преглед на логическата репликация в PostgreSQL

PostgreSQL е една от най-модерните бази данни с отворен код в света с много страхотни функции. Една от тях е поточно репликация (физическа репликация), която беше въведена в PostgreSQL 9.0. Базира се на XLOG записи, които се прехвърлят към сървъра местоназначение и се прилагат там. Въпреки това, той е базиран на клъстер и не можем да направим репликация на единична база данни или един обект (селективна репликация). През годините сме зависими от външни инструменти като Slony, Bucardo, BDR и т.н. за селективна или частична репликация, тъй като нямаше функция на основно ниво до PostgreSQL 9.6. Въпреки това, PostgreSQL 10 излезе с функция, наречена логическа репликация, чрез която можем да извършваме репликация на ниво база данни/обект.

Логическата репликация репликира промените на обекти въз основа на тяхната идентичност на репликация, която обикновено е първичен ключ. Тя е различна от физическата репликация, при която репликацията се основава на блокове и репликация байт по байт. Логическата репликация не се нуждае от точно двоично копие от страната на целевия сървър и ние имаме възможността да пишем на целевия сървър за разлика от физическата репликация. Тази функция произлиза от pglogical модула.

В тази публикация в блога ще обсъдим:

  • Как работи – Архитектура
  • Функции
  • Случаи на употреба – когато е полезно
  • Ограничения
  • Как да го постигнем

Как работи – Архитектура на логическа репликация

Логическата репликация реализира концепция за публикуване и абониране (публикация и абонамент). По-долу е представена архитектурна диаграма от по-високо ниво за това как работи.

Основна логическа репликационна архитектура

Публикацията може да бъде дефинирана на главния сървър и възелът, на който е дефиниран, се нарича "издател". Публикуването е набор от промени от една таблица или група таблици. Той е на ниво база данни и всяка публикация съществува в една база данни. Множество таблици могат да бъдат добавени към една публикация и една таблица може да бъде в множество публикации. Трябва да добавяте обекти изрично към публикация, освен ако изберете опцията „ВСИЧКИ ТАБЛИЦИ“, която се нуждае от привилегия на суперпотребител.

Можете да ограничите промените на обекти (INSERT, UPDATE и DELETE), които да бъдат репликирани. По подразбиране всички типове операции се репликират. Трябва да имате конфигурирана идентичност за репликация за обекта, който искате да добавите към публикация. Това е с цел репликиране на операции UPDATE и DELETE. Идентичността на репликацията може да бъде първичен ключ или уникален индекс. Ако таблицата няма първичен ключ или уникален индекс, тогава тя може да бъде настроена на идентичност на репликата „пълна“, в която приема всички колони като ключ (целият ред става ключ).

Можете да създадете публикация, като използвате CREATE PUBLICATION. Някои практически команди са разгледани в раздела „Как да го постигнем“.

Абонаментът може да бъде дефиниран на целевия сървър и възелът, на който е дефиниран, се нарича "абонат". Връзката с изходната база данни се дефинира в абонамента. Абонатният възел е същият като всяка друга самостоятелна база данни postgres и можете също да я използвате като публикация за допълнителни абонаменти.

Абонаментът се добавя чрез CREATE SUBSCRIPTION и може да бъде спрян/продължен по всяко време с командата ALTER SUBSCRIPTION и премахнат чрез DROP SUBSCRIPTION.

След като се създаде абонамент, логическата репликация копира моментна снимка на данните в базата данни на издателя. След като това бъде направено, той изчаква делта промени и ги изпраща до възела на абонамента веднага щом настъпят.

Как обаче се събират промените? Кой ги изпраща към целта? И кой ги прилага към целта? Логическата репликация също се основава на същата архитектура като физическата репликация. Реализира се чрез процеси "walsender" и "apply". Тъй като се основава на WAL декодиране, кой започва декодирането? Процесът на walsender е отговорен за стартиране на логическото декодиране на WAL и зарежда стандартния плъгин за логическо декодиране (pgoutput). Плъгинът трансформира промените, прочетени от WAL към протокола за логическа репликация, и филтрира данните според спецификацията на публикацията. След това данните се прехвърлят непрекъснато с помощта на протокола за поточно репликация към работника за прилагане, който картографира данните в локални таблици и прилага отделните промени при получаването им в правилен транзакционен ред.

Той регистрира всички тези стъпки в регистрационни файлове, докато го настройва. Можем да видим съобщенията в раздела „Как да го постигнем“ по-късно в публикацията.

Характеристики на логическата репликация

  • Логическата репликация репликира обекти с данни въз основа на тяхната идентичност на репликация (обикновено
  • първичен ключ или уникален индекс).
  • Целевият сървър може да се използва за запис. Можете да имате различни индекси и дефиниции за сигурност.
  • Логическата репликация има поддръжка за кръстосани версии. За разлика от поточно репликацията, логическата репликация може да се задава между различни версии на PostgreSQL (> 9.4, все пак)
  • Логическата репликация извършва филтриране въз основа на събития
  • В сравнение, логическата репликация има по-малко усилване при запис от поточно репликацията
  • Публикациите могат да имат няколко абонамента
  • Логическата репликация осигурява гъвкавост на съхранението чрез репликиране на по-малки набори (дори разделени таблици)
  • Минимално натоварване на сървъра в сравнение с базираните на тригер решения
  • Позволява паралелно поточно предаване между издатели
  • Логическата репликация може да се използва за миграции и надстройки
  • Преобразуването на данните може да се извърши по време на настройката.

Случаи на употреба – Кога е полезна логическата репликация?

Много е важно да знаете кога да използвате логическа репликация. В противен случай няма да получите голяма полза, ако вашият случай на употреба не съвпада. И така, ето някои случаи на употреба за това кога да използвате логическа репликация:

  • Ако искате да консолидирате множество бази данни в една база данни за аналитични цели.
  • Ако изискването ви е да репликирате данни между различни основни версии на PostgreSQL.
  • Ако искате да изпратите постепенни промени в една база данни или подмножество от база данни към други бази данни.
  • Ако давате достъп до репликирани данни на различни групи потребители.
  • Ако споделяте подмножество от базата данни между множество бази данни.

Ограничения на логическата репликация

Логическата репликация има някои ограничения, върху които общността непрекъснато работи за преодоляване:

  • Таблиците трябва да имат едно и също пълно квалифицирано име между публикацията и абонамента.
  • Таблиците трябва да имат първичен ключ или уникален ключ
  • Взаимната (двупосочна) репликация не се поддържа
  • Не копира схема/DDL
  • Не възпроизвежда последователности
  • Не копира TRUNCATE
  • Не копира големи обекти
  • Абонаментите могат да имат повече колони или различен ред на колони, но типовете и имената на колоните трябва да съвпадат между Публикация и Абонамент.
  • Права на суперпотребител за добавяне на всички таблици
  • Не можете да предавате поточно към същия хост (абонаментът ще бъде заключен).
Изтеглете Бялата книга днес Управление и автоматизация на PostgreSQL с ClusterControl Научете какво трябва да знаете, за да внедрите, наблюдавате, управлявате и мащабирате PostgreSQLD Изтеглете Бялата книга

Как да постигнем логическа репликация

Ето стъпките за постигане на основна логическа репликация. Можем да обсъдим по-сложни сценарии по-късно.

  1. Инициализирайте два различни екземпляра за публикуване и абонамент и стартирайте.

    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. Параметрите, които трябва да се променят, преди да стартирате екземплярите (както за екземпляри на публикация, така и за абонамент).

    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

    Други параметри могат да бъдат по подразбиране за основна настройка.

  3. Променете pg_hba.conf файла, за да разрешите репликация. Обърнете внимание, че тези стойности зависят от вашата среда, но това е само основен пример (както за публикации, така и за абонамент).

    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. Създайте няколко тестови таблици, за да репликирате и вмъкнете някои данни в екземпляр на публикация.

    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. Създайте структура на таблиците в екземпляр на абонамента, тъй като логическата репликация не репликира структурата.

    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. Създайте публикация на екземпляр на публикация (порт 5555).

    source_rep=# CREATE PUBLICATION mypub FOR TABLE test_rep, test_rep_other;
    CREATE PUBLICATION
    Time: 3.840 ms
    source_rep=#
  7. Създайте абонамент за екземпляр за подписване (порт 5556) за публикацията, създадена в стъпка 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

    От дневника:

    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

    Както можете да видите в съобщението NOTICE, той създаде слот за репликация, който гарантира, че почистването на WAL не трябва да се извършва, докато първоначалната моментна снимка или делта промените не бъдат прехвърлени към целевата база данни. След това подателят на WAL започна да декодира промените и прилагането на логическата репликация заработи, тъй като и pub, и sub са стартирани. След това стартира синхронизирането на таблицата.

  8. Проверете данните в екземпляра на абонамента.

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

    Както виждате, данните са репликирани чрез първоначална моментна снимка.

  9. Проверете делта промените.

    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$

Това са стъпките за основна настройка на логическа репликация.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Функцията low() за международни знаци в postgresql

  2. Използване на INSERT с PostgreSQL база данни с помощта на Python

  3. Нито една функция не съответства на даденото име и типове аргументи

  4. Картографиране на масив с Hibernate

  5. django.db.utils.ProgrammingError:връзката вече съществува