Перейти к содержанию
Learning Platform
Средний
25 минут
logical-decoding pgoutput wal publications

Требуемые знания:

  • module-1/02-debezium-architecture

Logical Decoding: Глубокое погружение

В предыдущем модуле мы узнали, что Debezium читает transaction log (WAL) PostgreSQL. Но как именно это происходит? В этом уроке мы погрузимся в механизм logical decoding — технологию, которая превращает бинарный WAL в понятный поток изменений.

Физическая vs Логическая репликация

PostgreSQL поддерживает два типа репликации. Понимание разницы критически важно для настройки CDC.

Physical Replication
PRIMARY
Бинарные WAL сегменты
STANDBY
Побайтовая копия данных
Только PostgreSQL → PostgreSQL
Вся база целиком
Logical Replication (CDC)Recommended
PRIMARY
pgoutput plugin
Logical Decoder
Структурированные изменения
Consumer (Debezium)
INSERT/UPDATE/DELETE события
Выборочные таблицы
Разные версии PostgreSQL
ХарактеристикаФизическаяЛогическая
Формат данныхБинарные блокиСтруктурированные изменения
ГранулярностьВся базаОтдельные таблицы
ПотребителиТолько PostgreSQLЛюбая система
Use caseHigh AvailabilityCDC, интеграции

Для CDC нам нужна логическая репликация, потому что мы хотим получать понятные события об изменениях, а не бинарные данные.

Что такое Logical Decoding?

Logical Decoding — это механизм PostgreSQL, который преобразует записи WAL в логический формат. Каждая транзакция декодируется в последовательность операций INSERT, UPDATE, DELETE с данными строк.

Компоненты Logical Decoding

WAL
Replication Slot
Logical Decoder
pgoutput
Debezium
Kafka

WAL (Write-Ahead Log) — журнал транзакций, куда PostgreSQL записывает каждое изменение ДО применения к таблицам. Гарантирует durability.

Replication Slot — закладка в WAL. PostgreSQL не удаляет WAL сегменты, пока слот их не прочитал. Критически важно для надежности CDC.

Logical Decoder — компонент PostgreSQL, который интерпретирует WAL записи в контексте транзакций.

Output Plugin — форматирует декодированные изменения. pgoutput — стандартный плагин PostgreSQL 10+.

pgoutput: Стандартный плагин

pgoutput — это встроенный output plugin PostgreSQL для логической репликации. Именно его использует Debezium.

Почему pgoutput — стандарт для Debezium?

ПлагинСтатусОсобенности
pgoutputВстроенный (PG 10+)Не требует установки, работает на Aurora/RDS
wal2jsonСтороннийJSON формат, требует установки, больше overhead
decoderbufsСтороннийProtobuf формат, недоступен на Aurora

Рекомендация: Всегда используйте pgoutput. Это единственный плагин, который:

  • Не требует установки дополнительного ПО
  • Работает на всех managed PostgreSQL (Aurora, RDS, Cloud SQL)
  • Поддерживается командой PostgreSQL
{
  "name": "postgres-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "plugin.name": "pgoutput",
    "database.hostname": "postgres",
    "database.port": "5432",
    "database.user": "postgres",
    "database.dbname": "inventory"
  }
}
Проверка знаний
Почему pgoutput рекомендуется для Debezium, даже если wal2json выдаёт более читаемый JSON?
Ответ
pgoutput встроен в PostgreSQL 10+ и не требует установки дополнительного ПО. Он работает на всех managed PostgreSQL (Aurora, RDS, Cloud SQL). wal2json — сторонний плагин, который часто невозможно установить на managed-сервисах.

Анатомия WAL для Logical Decoding

Когда вы выполняете транзакцию, PostgreSQL записывает её в WAL. При wal_level=logical добавляется дополнительная информация для декодирования.

Что содержит WAL запись при logical decoding?

┌─────────────────────────────────────────────────────┐
│                    WAL Record                       │
├─────────────────────────────────────────────────────┤
│ LSN (Log Sequence Number): 0/1A3B4C0                │
│ Transaction ID: 12345                               │
│ Timestamp: 2026-02-01 10:30:00.123                  │
│ Operation: UPDATE                                   │
│ Relation: public.customers (OID: 16384)             │
│ Old tuple key: {id: 1}                              │
│ New tuple: {id: 1, name: 'Alice', email: '...'}     │
└─────────────────────────────────────────────────────┘

LSN (Log Sequence Number) — уникальный идентификатор позиции в WAL. Debezium использует LSN для отслеживания прогресса.

Transaction ID — группирует изменения одной транзакции. Debezium публикует события с одним transaction ID атомарно.

Old/New tuple — старые и новые значения строки. Доступность старых значений зависит от REPLICA IDENTITY.

Publications: Контроль над тем, что реплицируется

Publication — это набор таблиц, изменения которых будут доступны для логической репликации. Debezium использует publications для фильтрации таблиц.

База данных inventory
customers
orders
products
audit_logs
FOR ALL TABLES
dbz_publication
+ customers
+ orders
+ products
+ audit_logs
+ future tables...
FOR TABLE (selective)
orders_publication
+ orders
+ customers
- products
- audit_logs

Создание Publication

-- Публикация для всех таблиц (рекомендуется для начала)
CREATE PUBLICATION dbz_publication FOR ALL TABLES;

-- Публикация только для конкретных таблиц
CREATE PUBLICATION orders_publication
FOR TABLE public.orders, public.customers;

-- Публикация с фильтрацией операций
CREATE PUBLICATION inserts_only
FOR TABLE public.events
WITH (publish = 'insert');  -- Только INSERT, без UPDATE/DELETE

Проверка существующих Publications

-- Список всех publications
SELECT * FROM pg_publication;

-- Таблицы в publication
SELECT * FROM pg_publication_tables
WHERE pubname = 'dbz_publication';

Как Debezium использует Publications

В конфигурации коннектора указывается имя publication:

{
  "name": "inventory-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "plugin.name": "pgoutput",
    "publication.name": "dbz_publication",
    "publication.autocreate.mode": "filtered"
  }
}

publication.autocreate.mode:

  • all_tables — создать для всех таблиц (по умолчанию)
  • filtered — создать только для таблиц из table.include.list
  • disabled — использовать существующую publication

REPLICA IDENTITY: Что попадает в before/after

REPLICA IDENTITY определяет, какие данные PostgreSQL включает в WAL при UPDATE и DELETE. Это критически влияет на содержимое CDC событий.

Четыре режима REPLICA IDENTITY

РежимUPDATE beforeDELETE beforeOverhead
DEFAULTТолько PKТолько PKМинимальный
USING INDEXКолонки индексаКолонки индексаНизкий
FULLВся строкаВся строкаВысокий
NOTHINGПустоПустоНулевой

Пример события при разных REPLICA IDENTITY

REPLICA IDENTITY DEFAULT (Primary Key):

{
  "op": "u",
  "before": {
    "id": 1
  },
  "after": {
    "id": 1,
    "name": "Alice Updated",
    "email": "[email protected]"
  }
}

REPLICA IDENTITY FULL:

{
  "op": "u",
  "before": {
    "id": 1,
    "name": "Alice",
    "email": "[email protected]"
  },
  "after": {
    "id": 1,
    "name": "Alice Updated",
    "email": "[email protected]"
  }
}

Когда использовать FULL?

Используйте REPLICA IDENTITY FULL когда:

  1. Нужно знать, что именно изменилось — сравнение before/after
  2. Потребителю нужны все поля до изменения — аудит, compliance
  3. Логика обработки зависит от старых значений
-- Включить FULL для конкретной таблицы
ALTER TABLE public.customers REPLICA IDENTITY FULL;

-- Проверить текущую настройку
SELECT relname, relreplident
FROM pg_class
WHERE relname = 'customers';
-- relreplident: 'd' = DEFAULT, 'f' = FULL, 'i' = INDEX, 'n' = NOTHING
Проверка знаний
Таблица имеет REPLICA IDENTITY DEFAULT. Какие данные будут в поле before при UPDATE-событии?
Ответ
Только колонки Primary Key. При DEFAULT PostgreSQL записывает в WAL минимум информации для идентификации строки. Для получения всех колонок в before необходимо переключить на REPLICA IDENTITY FULL, но это увеличит объём WAL на 30-50% для UPDATE-heavy таблиц.

Предупреждение о производительности

REPLICA IDENTITY FULL увеличивает объем WAL. Каждый UPDATE и DELETE записывает полную строку в WAL. Для таблиц с частыми изменениями и широкими строками (много колонок, JSONB) это может увеличить WAL volume на 30-50%.

Рекомендация: используйте DEFAULT для большинства таблиц, FULL — только где действительно необходимо.

Полный поток Logical Decoding

Соединим все компоненты в единый поток.

App
PostgreSQL
WAL
Slot
pgoutput
Debezium
Kafka
UPDATE customers...Write (FULL tuple)COMMIT OKRequest changesDecode WALLogical changeCDC EventACKConfirm LSN

Ключевые точки

  1. wal_level=logical — обязательная настройка PostgreSQL
  2. Replication Slot — гарантирует, что WAL не удалится до прочтения
  3. pgoutput — преобразует бинарный WAL в структурированные данные
  4. Publication — определяет, какие таблицы реплицируются
  5. REPLICA IDENTITY — определяет полноту данных в before/after

Проверка настроек

-- Проверить wal_level
SHOW wal_level;
-- Должно быть: logical

-- Проверить существующие слоты
SELECT slot_name, plugin, slot_type, active
FROM pg_replication_slots;

-- Проверить publications
SELECT pubname, puballtables
FROM pg_publication;

-- Проверить REPLICA IDENTITY для таблицы
SELECT c.relname, c.relreplident
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'public' AND c.relkind = 'r';

Что дальше?

Теперь, когда вы понимаете, как PostgreSQL преобразует WAL в логические изменения, следующий важный вопрос: как управлять replication slots?

Slots — это мощный механизм, но они требуют внимания. Abandoned slot может заполнить диск, остановив базу данных. В следующем уроке мы изучим жизненный цикл replication slots и критически важные процедуры мониторинга.

Ключевые выводы

  1. Logical Decoding преобразует бинарный WAL в понятные события INSERT/UPDATE/DELETE
  2. pgoutput — стандартный плагин, работает везде, не требует установки
  3. Publications контролируют, какие таблицы участвуют в логической репликации
  4. REPLICA IDENTITY определяет полноту данных — DEFAULT для эффективности, FULL для полной истории
  5. Replication Slots гарантируют, что Debezium не пропустит изменения

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 7. В чём принципиальное различие между физической и логической репликацией в PostgreSQL?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс