--- aliases: tags: - maturity/🌱 date: - - 2024-06-17 zero-link: - "[[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]" parents: - "[[РСпликация Π² PostgreSQL|РСпликация Π² PostgreSQL]]" linked: --- ## ЀизичСская рСпликация Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠ΅Ρ‚ΡŒ, Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ адрСс ```shell docker network create pgnet docker network inspect pgnet | grep Subnet # Π—Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ маску сСти ``` ПоднимаСм мастСр ```shell docker run -dit -v "$PWD/volumes/pgmaster/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "5432:5432" --restart=unless-stopped --network=pgnet --name=pgmaster postgres ``` МСняСм postgresql.conf Π½Π° мастСрС ```conf ssl = off wal_level = replica max_wal_senders = 4 # expected slave num ``` ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡΡ ΠΊ мастСру ΠΈ создаСм ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ для Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ```shell docker exec -it pgmaster su - postgres -c psql create role replicator with login replication password 'pass'; exit ``` ДобавляСм запись Π² `pgmaster/pg_hba.conf` с `subnet` с ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ шага ``` host replication replicator __SUBNET__ md5 ``` ΠŸΠ΅Ρ€Π΅Π·Π°ΠΏΡƒΡΡ‚ΠΈΠΌ мастСр ```shell docker restart pgmaster ``` Π‘Π΄Π΅Π»Π°Π΅ΠΌ бэкап для Ρ€Π΅ΠΏΠ»ΠΈΠΊ ```shell docker exec -it pgmaster bash mkdir /pgslave pg_basebackup -h pgmaster -D /pgslave -U replicator -v -P --wal-method=stream exit ``` ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ сСбС ```shell docker cp pgmaster:/pgslave volumes/pgslave/ ``` Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Ρ„Π°ΠΉΠ», Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° ΡƒΠ·Π½Π°Π»Π°, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° ```shell touch volumes/pgslave/standby.signal ``` МСняСм `postgresql.conf` Π½Π° Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ΅ `pgslave` ```conf primary_conninfo = 'host=pgmaster port=5432 user=replicator password=pass application_name=pgslave' ``` ЗапускаСм Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgslave` ```shell docker run -dit -v "$PWD/volumes/pgslave/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "15432:5432" --network=pgnet --restart=unless-stopped --name=pgslave postgres ``` Запустим Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgasyncslave` Π‘ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ бэкап ```shell docker cp pgmaster:/pgslave volumes/pgasyncslave/ ``` ИзмСним настройки `pgasyncslave/postgresql.conf` ```conf primary_conninfo = 'host=pgmaster port=5432 user=replicator password=pass application_name=pgasyncslave' ``` Π”Π°Π΄ΠΈΠΌ Π·Π½Π°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ это Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° ```shell touch volumes/pgasyncslave/standby.signal ``` Запустим Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgasyncslave` ```shell docker run -dit -v "$PWD/volumes/pgasyncslave/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "25432:5432" --network=pgnet --restart=unless-stopped --name=pgasyncslave postgres ``` УбСТдаСмся Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² асинхронном Ρ€Π΅ΠΆΠΈΠΌΠ΅ Π½Π° `pgmaster` ```shell docker exec -it pgmaster su - postgres -c psql select application_name, sync_state from pg_stat_replication; exit; ``` Π’ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡŽ Π½Π° `pgmaster` МСняСм Ρ„Π°ΠΉΠ» `pgmaster/postgresql.conf` ```conf synchronous_commit = on synchronous_standby_names = 'FIRST 1 (pgslave, pgasyncslave)' ``` ΠŸΠ΅Ρ€Π΅Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅ΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ ```shell docker exec -it pgmaster su - postgres -c psql select pg_reload_conf(); exit; ``` УбСТдаСмся, Ρ‡Ρ‚ΠΎ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° стала синхронной ```shell docker exec -it pgmaster su - postgres -c psql select application_name, sync_state from pg_stat_replication; exit; ``` Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Ρ‚Π΅ΡΡ‚ΠΎΠ²ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π½Π° `pgmaster` ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡŽ ```shell docker exec -it pgmaster su - postgres -c psql create table test(id bigint primary key not null); insert into test(id) values(1); select * from test; exit; ``` ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π° `pgslave` ```shell docker exec -it pgslave su - postgres -c psql select * from test; exit; ``` ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π° `pgasyncslave` ```shell docker exec -it pgasyncslave su - postgres -c psql select * from test; exit; ``` ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ `insert` Π½Π° `pgslave` ```shell docker exec -it pgslave su - postgres -c psql insert into test(id) values(2); exit; ``` Π£ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅ΠΌ Ρ€Π΅ΠΏΠΈΠ»ΠΊΡƒ `pgasyncslave` ΠΈ провСряСм Ρ€Π°Π±ΠΎΡ‚Ρƒ `pgmaster` ΠΈ `pgslave` ```shell docker stop pgasyncslave docker exec -it pgmaster su - postgres -c psql select application_name, sync_state from pg_stat_replication; insert into test(id) values(2); select * from test; exit; docker exec -it pgslave su - postgres -c psql select * from test; exit; ``` Π£ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅ΠΌ Ρ€Π΅ΠΏΠΈΠ»ΠΊΡƒ `pgslave` ΠΈ провСряСм Ρ€Π°Π±ΠΎΡ‚Ρƒ `pgmaster`, Π° ΠΏΠΎΡ‚ΠΎΠΌ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgslave` terminal 1 ```shell docker stop pgslave docker exec -it pgmaster su - postgres -c psql select application_name, sync_state from pg_stat_replication; insert into test(id) values(3); exit; ``` terminal 2 ```shell docker start pgslave ``` Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgasyncslave` ```shell docker start pgasyncslave ``` Π£Π±ΠΈΠ²Π°Π΅ΠΌ мастСр `pgmaster` ```shell docker stop pgmaster ``` Π—Π°ΠΏΡ€ΠΎΠΌΠΎΡƒΡ‚ΠΈΠΌ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgslave` ```shell docker exec -it pgslave su - postgres -c psql select pg_promote(); exit; ``` ΠŸΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π² Π½ΠΎΠ²Ρ‹ΠΉ мастСр `pgslave` ```shell docker exec -it pgslave su - postgres -c psql insert into test(id) values(4); exit; ``` НастраиваСм Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡŽ Π½Π° `pgslave` (`pgslave/postgresql.conf`) измСняСм ΠΊΠΎΠ½Ρ„ΠΈΠ³ ```conf synchronous_commit = on synchronous_standby_names = 'ANY 1 (pgmaster, pgasyncslave)' ``` ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅ΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ ```shell docker exec -it pgslave su - postgres -c psql select pg_reload_conf(); exit; ``` ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠΌ Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ `pgasyncslave` ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ мастСру `pgslave` измСняСм ΠΊΠΎΠ½Ρ„ΠΈΠ³ `pgasyncslave/postgresql.conf` ```conf primary_conninfo = 'host=pgslave port=5432 user=replicator password=pass application_name=pgasyncslave' ``` ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅ΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ ```shell docker exec -it pgasyncslave su - postgres -c psql select pg_reload_conf(); exit; ``` ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ Ρ‡Ρ‚ΠΎ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ мастСру `pgslave` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π° Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° ΠΈ ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ```shell docker exec -it pgslave su - postgres -c psql select application_name, sync_state from pg_stat_replication; insert into test(id) values (5) select * from test; exit; docker exec -it pgasyncslave su - postgres -c psql select * from test; exit; ``` Восстановим старый мастСр `pgmaster` ΠΊΠ°ΠΊ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ ΠŸΠΎΠΌΠ΅Ρ‡Π°Π΅ΠΌ ΠΊΠ°ΠΊ Ρ€Π΅ΠΏΠ»ΠΈΠΊΡƒ ```shell touch volumes/pgmaster/standby.signal ``` ИзмСняСм ΠΊΠΎΠ½Ρ„ΠΈΠ³ `pgmaster/postgresql.conf` ```conf primary_conninfo = 'host=pgslave port=5432 user=replicator password=pass application_name=pgmaster' ``` Запустим `pgmaster` ```shell docker start pgmaster ``` УбСдимся Ρ‡Ρ‚ΠΎ `pgmaster` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΡΡ ΠΊΠ°ΠΊ Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ° ΠΊ `pgslave` ```shell docker exec -it pgslave su - postgres -c psql select application_name, sync_state from pg_stat_replication; exit; ``` ## ЛогичСская рСпликация МСняСм `wal_level` для Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ мастСра `pgslave` ИзмСняСм настройки `pgslave/postgresql.conf` ```conf wal_level = logical ``` ΠŸΠ΅Ρ€Π΅Π·Π°ΠΏΡƒΡΠΊΠ°Π΅ΠΌ `pgslave` ```shell docker restart pgslave ``` Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΡŽ Π² `pgslave` ```shell docker exec -it pgslave su - postgres -c psql GRANT CONNECT ON DATABASE postgres TO replicator; GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator; create publication pg_pub for table test; exit; ``` Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π½ΠΎΠ²Ρ‹ΠΉ сСрвСр `pgstandalone` для логичСской Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ```shell docker run -dit -v "$PWD/volumes/pgstandalone/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "35432:5432" --restart=unless-stopped --network=pgnet --name=pgstandalone postgres ``` ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Ρ„Π°ΠΉΠ»Ρ‹ c `pgslave` Π² `pgstandalone` ΠΈ восстанавливаСм ```shell docker exec -it pgslave su - postgres pg_dumpall -U postgres -r -h pgslave -f /var/lib/postgresql/roles.dmp pg_dump -U postgres -Fc -h pgslave -f /var/lib/postgresql/schema.dmp -s postgres exit; docker cp pgslave:/var/lib/postgresql/roles.dmp . docker cp roles.dmp pgstandalone:/var/lib/postgresql/roles.dmp docker cp pgslave:/var/lib/postgresql/schema.dmp . docker cp schema.dmp pgstandalone:/var/lib/postgresql/schema.dmp docker exec -it pgstandalone su - postgres psql -f roles.dmp pg_restore -d postgres -C schema.dmp exit ``` Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ подписку Π½Π° `pgstandalone` ```shell docker exec -it pgstandalone su - postgres -c psql CREATE SUBSCRIPTION pg_sub CONNECTION 'host=pgslave port=5432 user=replicator password=pass dbname=postgres' PUBLICATION pg_pub; exit; ``` УбСТдаСмся Ρ‡Ρ‚ΠΎ рСпликация Π·Π°ΠΏΡƒΡ‰Π΅Π½Π° ```shell docker exec -it pgstandalone su - postgres -c psql select * from test; exit; ``` Π‘Π΄Π΅Π»Π°Π΅ΠΌ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ Π² Π΄Π°Π½Π½Ρ‹Ρ… ВставляСм Π΄Π°Π½Π½Ρ‹Π΅ Π² подписчикС `pgstandalone` ```shell docker exec -it pgstandalone su - postgres -c psql insert into test values(9); exit; ``` ВставляСм Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΏΠ°Π±Π»ΠΈΡˆΠ΅Ρ€Π΅ `pgslave` ```shell docker exec -it pgslave su - postgres -c psql insert into test values(9); insert into test values(10); exit; ``` УбСТдаСмся Ρ‡Ρ‚ΠΎ записи с id 10 Π½Π΅ появилось Π½Π° `pgstandalone` ```shell docker exec -it pgstandalone su - postgres -c psql select * from test; exit; ``` ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ Π² Π»ΠΎΠ³ΠΈ `pgstandalone` ΠΈ убСдимся Ρ‡Ρ‚ΠΎ Ρƒ нас ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ΅Π» Ρ€Π°Π·Ρ€Ρ‹Π² Ρ€Π΅ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ```shell docker logs pgstandalone 2023-03-27 16:15:02.753 UTC [258] ERROR: duplicate key value violates unique constraint "test_pkey" 2023-03-27 16:15:02.753 UTC [258] DETAIL: Key (id)=(9) already exists. 2023-03-28 18:30:42.893 UTC [108] CONTEXT: processing remote data for replication origin "pg_16395" during message type "INSERT" for replication target relation "public.test" in transaction 739, finished at 0/3026450 ``` Π˜ΡΠΏΡ€Π°Π²Π»ΡΠ΅ΠΌ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ ```shell docker exec -it pgstandalone su - postgres -c psql SELECT pg_replication_origin_advance('pg_16395', '0/3026451'::pg_lsn); # message from log + 1 ALTER SUBSCRIPTION pg_sub ENABLE; select * from test; exit; ``` *** ## ΠœΠ΅Ρ‚Π° информация **ΠžΠ±Π»Π°ΡΡ‚ΡŒ**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]] **Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ**:: [[РСпликация Π² PostgreSQL|РСпликация Π² PostgreSQL]] **Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ**:: **Автор**:: **Π‘ΠΎΠ·Π΄Π°Π½Π°**:: [[2024-06-17]] ### Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ - ### Π”ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ