PostgreSQL

Logical Replication: публикации и подписки

PostgreSQL 14 работает в production 3 года. Вышел PostgreSQL 16 с огромными улучшениями планировщика. Как обновиться без 8 часов downtime? В 2017 году это была нерешаемая задача. Сегодня: logical replication между pg14 и pg16 синхронизирует данные за несколько часов, переключение трафика - 30 секунд. Zalando обновляет Postgres на 500+ инстансах именно так. Logical replication - это инструмент, который делает PostgreSQL живым организмом, способным меняться без остановки.

  • **Zalando** - zero-downtime major version upgrades через logical replication: обновление 500+ PostgreSQL инстансов с downtime менее 30 секунд на каждый
  • **Stripe** - row-filter publications для GDPR: EU-данные реплицируются только в EU-датацентры, US - только в US. Фильтрация по region в PUBLICATION на уровне PostgreSQL
  • **Supabase** - logical replication для point-in-time branching: создание ветки БД для разработки через subscription на production, актуальные данные без dump/restore

Logical vs Physical Replication

**Physical replication копирует весь кластер побайтово. Logical replication - только выбранные таблицы, в логическом формате (INSERT/UPDATE/DELETE).** Физическая быстрее и проще, но реплика должна быть identical версии PostgreSQL и архитектуры. Logical позволяет реплицировать между разными версиями, фильтровать таблицы, реплицировать в обе стороны.

ХарактеристикаPhysical (Streaming)Logical
Единица репликацииВесь кластерОтдельные таблицы/схемы
Версии PostgreSQLДолжны совпадатьРазные (в обе стороны)
НаправлениеТолько primary→standbyДвунаправленная возможна
DDL (CREATE TABLE)АвтоматическиНе реплицируется
Объём WALВесь WALТолько отмеченные таблицы
Standby - writeable?Нет (read-only)Да

**Главные применения logical replication:** zero-downtime major upgrade (pg15 → pg16), репликация подмножества таблиц в analytics DB, bi-directional replication, шардинг через Citus, синхронизация данных между регионами.

Команда обновляет PostgreSQL 14 → 16 без downtime. Какой тип репликации позволяет это сделать?

PUBLICATION: что реплицировать

**PUBLICATION** определяет набор таблиц для логической репликации - это издатель. Можно публиковать все таблицы, конкретный список, или таблицы с фильтрацией по строкам (PostgreSQL 15+). Publication - объект на publisher-стороне (primary).

**DDL не реплицируется через logical replication.** Если на publisher добавлен столбец в таблицу - на subscriber нужно сделать ALTER TABLE вручную до применения изменений. Это главное ограничение по сравнению с physical replication.

PUBLICATION создана для таблицы `users`. На publisher выполнен `ALTER TABLE users ADD COLUMN last_login timestamptz`. Что нужно сделать на subscriber?

SUBSCRIPTION: подписка на изменения

**SUBSCRIPTION** - объект на subscriber-стороне, описывающий подключение к publisher и список publications. При создании subscription PostgreSQL автоматически копирует начальные данные (initial data copy) и затем начинает принимать поток изменений. Subscriber может быть полноценной writeable БД.

**`DROP SUBSCRIPTION` автоматически удаляет replication slot на publisher.** Это важно: в отличие от ручного удаления слота, DROP SUBSCRIPTION делает cleanup корректно. Если subscriber недоступен - нужно удалить слот на publisher вручную через `pg_drop_replication_slot()`.

Subscription создана с copy_data=true. Что происходит сразу после CREATE SUBSCRIPTION?

Selective Replication: фильтры строк и столбцов

**PostgreSQL 15+ позволяет фильтровать строки в PUBLICATION, 16+ - выбирать отдельные столбцы.** Это открывает архитектурные возможности: реплицировать только данные конкретного региона, маскировать PII-поля в analytics replica, реплицировать только активных пользователей для ML-задач.

**Использование в production:** Stripe реплицирует данные американских транзакций только в US-датацентры, европейских - в EU (GDPR compliance). Фильтрация по region в PUBLICATION гарантирует, что данные европейцев физически не покидают EU.

PUBLICATION создана с `WHERE (region = 'EU')`. Заказ с region='US' обновлён, region изменён на 'EU'. Что получит subscriber?

Ограничения Logical Replication

**Logical replication имеет принципиальные ограничения, которые нужно знать до выбора архитектуры.** Понимание ограничений позволяет избежать сюрпризов в production и выбрать правильный подход для конкретной задачи.

**Sequences - главная ловушка при bi-directional replication.** Если обе стороны генерируют serial ID - рано или поздно конфликт. Стандартные решения: разные диапазоны ID (A генерирует 1..500M, B генерирует 500M..1B), или UUID, или генерация только на одной стороне.

**Zero-downtime upgrade PostgreSQL 14→16** через logical replication: создать pg16, создать subscription на pg14, дождаться sync, переключить трафик. Единственное ограничение - нужно применить все DDL-изменения на pg16 вручную до старта subscription.

Logical replication - полная замена physical replication, просто более гибкая

Logical и physical replication решают разные задачи. Physical - HA и failover для всего кластера. Logical - избирательная репликация, cross-version upgrade, CDC. В production часто используют оба: physical для HA standby, logical для analytics replica или upgrade

Physical replication автоматически реплицирует DDL, sequences, системные каталоги. Logical - только DML для явно указанных таблиц. Failover через logical replication требует ручной синхронизации sequences и применения DDL - это сложно. Patroni для HA всегда строится поверх physical replication

Bi-directional logical replication между двумя датацентрами. Пользователь A вставляет запись с id=100 в DC1, одновременно пользователь B вставляет запись с id=100 в DC2. Что произойдёт?

Итоги

  • **Logical vs physical**: logical реплицирует избранные таблицы между любыми версиями, physical - весь кластер побайтово только между идентичными версиями
  • **PUBLICATION** (publisher) определяет что реплицировать. **SUBSCRIPTION** (subscriber) - куда и как подключаться
  • **DDL не реплицируется** - главное ограничение. ALTER TABLE нужно применять на subscriber вручную синхронно с publisher
  • **Row/column filtering** (pg15+/pg16+) позволяет реплицировать только нужные строки и столбцы - GDPR compliance, analytics без PII
  • **Sequences не реплицируются** - при bi-directional replication обязательны UUID или разные диапазоны ID

Связанные темы

Logical replication строится поверх WAL и logical decoding:

  • LISTEN/NOTIFY и Logical Decoding — Logical replication использует те же replication slots и output plugins что и CDC через pg_recvlogical/Debezium
  • Streaming Replication — Комплементарная технология: physical для HA standby + failover, logical для cross-version upgrade и analytics replica
  • Обновление PostgreSQL — Zero-downtime major upgrade через logical replication - стандартный подход для больших production баз

Вопросы для размышления

  • Нужно реплицировать таблицу `transactions` в analytics PostgreSQL без PII-полей (card_number, user_name). Как настроить PUBLICATION чтобы гарантированно не передавать эти поля? Что изменится если UPDATE меняет только non-PII поле?
  • После настройки bi-directional replication оба датацентра используют SERIAL для ID. Через неделю - конфликты. Как переделать схему чтобы конфликты были невозможны без остановки приложения?
  • Zero-downtime upgrade pg14→pg16 через logical replication. На pg14 таблица имеет 50 столбцов, 3 из которых добавили на прошлой неделе. Как убедиться что pg16 готов к приёму subscription прежде чем её создать?

Связанные уроки

  • dist-11-replication
Logical Replication: публикации и подписки

0

1

Войти