lesson ── postgres-labs ── ~22 мин ── 8 шагов
Раньше эта лаба показывала только источник-сторону на одном сервере. Теперь у тебя два независимых кластера: publisher (узел pg) с заранее поднятым wal_level=logical и отдельный subscriber. У тебя два пульта: вкладка pub смотрит на publisher, sub - на subscriber.
Ты объявишь публикацию, заведёшь подписку и проведёшь строку от источника к приёмнику. Каждый шаг сначала предскажи вывод, потом проверь на нужном узле.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
На вкладке pub (это publisher) спроси уровень журнала. По умолчанию у сервера replica, но логическому потоку нужен logical, и для этой лабы он поднят заранее.
SHOW wal_level;
Предскажи: какое значение вернёт источник?
logical больше, чем replica, и включается заранее с рестартом сервера.
✓ wal_level=logical - источник готов отдавать поток изменений построчно.
Всё ещё на pub. Публикация - объявленный набор таблиц, изменения которых источник готов отдавать подписчикам.
CREATE PUBLICATION pub_demo FOR TABLE repl_demo;
Предскажи: появится ли строка в pg_publication сразу после создания?
✓ Публикация pub_demo создана на источнике.
Какие таблицы реально попали в публикацию, видно в pg_publication_tables.
SELECT pubname, tablename FROM pg_publication_tables WHERE pubname='pub_demo';
Предскажи имя таблицы, которое окажется в выводе.
✓ В публикации одна таблица - repl_demo.
Переключись на вкладку sub (это subscriber, отдельный кластер). Схема repl_demo у него есть, но подписки пока нет.
SELECT count(*) FROM repl_demo;
Предскажи: сколько строк сейчас в repl_demo на приёмнике?
✓ На приёмнике пусто - база для чистого опыта: всё, что приедет, приедет по подписке.
Остаёмся на sub. Подписка открывает коннект к источнику и начинает тянуть изменения опубликованных таблиц. Источник доступен по имени pg, роль replicator уже заведена.
CREATE SUBSCRIPTION sub_demo
CONNECTION 'host=pg dbname=lab user=replicator password=replpass'
PUBLICATION pub_demo;
Предскажи: появится ли подписка в pg_subscription после команды?
Источник пуст, поэтому начальная синхронизация скопирует ноль строк - подписка встанет быстро.
✓ Подписка sub_demo создана и подключилась к источнику.
Вернись на вкладку pub (publisher). Вставь одну строку в опубликованную таблицу.
INSERT INTO repl_demo (id, note) VALUES (1, 'logical');
Предскажи: появится ли строка на источнике сразу?
✓ Строка на источнике записана и ушла в поток подписки.
Переключись на sub. Ты ничего сюда не вставлял: строка может появиться только по подписке, применённой из потока источника.
SELECT note FROM repl_demo WHERE id = 1;
Предскажи: окажется ли здесь строка 'logical', которую ты вставил на источнике?
Если пусто - проверка повторится; дай подписчику мгновение применить изменение.
✓ Строка доехала по логической подписке - источник отдал, приёмник применил.
Остаёмся на sub. Подписку надо снимать командой DROP SUBSCRIPTION: она же закроет коннект к источнику и уберёт его слот.
DROP SUBSCRIPTION sub_demo;
Предскажи, что вернёт count по pg_subscription после удаления.
✓ Подписка снята, слот на источнике освобождён. Приёмник-сторона разобрана.
Логическая репликация шлёт строки, а не байты WAL, и требует wal_level=logical на источнике. Источник объявляет PUBLICATION (набор таблиц), приёмник заводит SUBSCRIPTION и применяет изменения. Это два независимых кластера: приёмник открыт на запись. DDL и последовательности так не реплицируются.
команды
CREATE PUBLICATION p FOR TABLE t;объявить таблицы на источникеCREATE SUBSCRIPTION s CONNECTION '...' PUBLICATION p;подписаться на приёмникеSELECT * FROM pg_publication_tables;что реально попало в публикациюSELECT subname, subenabled FROM pg_subscription;подписки приёмникаконцепции