linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Репликация/distributed-pitfalls

kb/replication ── Репликация ── advanced

Распределённые ловушки: 2PC, multi-master, CAP

Как только данные живут на нескольких серверах, появляются проблемы, которых не было на одном. 2PC даёт атомарность поверх узлов, но повисший prepared-транзакшн держит блокировки и горизонт. Самодельный multi-master ловит конфликты записи, которые некому разрешить. CAP/PACELC объясняют, чем именно приходится жертвовать.

view as markdownaka: two-phase-commit, multi-master

Один сервер прощает то, чего не прощает кластер

На одном сервере транзакция либо целиком закоммичена, либо целиком откачена, и порядок изменений однозначен. Разнесли данные по узлам - и каждое из этих свойств приходится покупать отдельно, обычно за задержку или за риск.

Two-phase commit (2PC)

PREPARE TRANSACTION 'имя' разбивает COMMIT на два шага: сначала все узлы голосуют «готов зафиксировать» и доводят запись до durable, потом координатор шлёт всем COMMIT PREPARED. Так несколько баз фиксируют изменение атомарно.

Ловушка - между фазами. Prepared-транзакция уже не откатится сама: она ждёт решения координатора и держит все свои блокировки и свой xmin. Если координатор упал и не пришёл с вердиктом, она висит. А пока висит:

  • её блокировки никто не снимет;
  • её xmin держит горизонт - vacuum не чистит мёртвые версии во всём кластере, копится bloat;
  • max_prepared_transactions ограничен, повисшие забивают лимит.
sql
-- повисшие prepared-транзакции; разрешаются вручную
SELECT gid, prepared, owner, database FROM pg_prepared_xacts;
-- ROLLBACK PREPARED 'gid';  -- или COMMIT PREPARED 'gid';

Поэтому 2PC без надёжного координатора (или мониторинга pg_prepared_xacts) опаснее, чем кажется.

Самодельный multi-master

Соблазн: настроить логическую репликацию в обе стороны и писать в любой узел. На демо работает. В проде ломается на первом же конфликте:

  • Конфликт первичного ключа. Два узла выдали id = 1001 разным строкам (последовательности независимы). Прилетела чужая строка с уже занятым ключом - apply-воркер встал.
  • Конфликт записи. Одну строку обновили на обоих узлах одновременно. Кто прав? Встроенного разрешения у PostgreSQL нет - репликация по этой подписке просто останавливается до ручного вмешательства.
  • Циклы. Без аккуратной настройки origin изменение уезжает на соседа и возвращается обратно бесконечно.

Вывод не «нельзя», а «это отдельная распределённая система со своей политикой разрешения конфликтов, а не галочка в конфиге». Если нужен multi-master - берут специализированное решение, а не два CREATE SUBSCRIPTION навстречу друг другу.

CAP и PACELC одной фразой

CAP: при разрыве сети (Partition) между узлами выбираешь либо отвечать на запросы и рисковать рассогласованием (Availability), либо отказывать ради согласованности (Consistency). Третьего во время разрыва нет.

PACELC честнее: разрыв (P) - выбор A или C; а Else (когда сети нормальные) - всё равно выбор между задержкой (Latency) и согласованностью (C). Синхронный standby - это явный выбор C над L: каждый COMMIT ждёт подтверждения и потому медленнее. Асинхронный - выбор L над C: быстро, но реплика отстаёт и при падении primary можно потерять хвост транзакций.

Связано с streaming-replication (синхронный против асинхронного) и logical-replication (откуда берутся конфликты записи).

§ команды

bash
SELECT gid, prepared, owner FROM pg_prepared_xacts;

Повисшие prepared-транзакции - держат блокировки и горизонт

bash
SHOW max_prepared_transactions;

Лимит одновременных prepared-транзакций (0 - 2PC выключен)

bash
ROLLBACK PREPARED 'gid';

Снять повисшую prepared-транзакцию вручную, освободив её блокировки

§ см. также

  • streaming-replicationФизическая (потоковая) репликацияStandby проигрывает у себя тот же WAL, что пишет primary, и получается побайтовая копия кластера. Primary отдаёт журнал процессом walsender, standby принимает walreceiver'ом и применяет startup-процессом. Лаг меряется в LSN: насколько replay на standby отстал от записи на primary.
  • logical-replicationЛогическая репликация (publication/subscription)Логическая репликация шлёт не байты WAL, а декодированные изменения строк: INSERT/UPDATE/DELETE по конкретным таблицам. Источник объявляет PUBLICATION, приёмник создаёт SUBSCRIPTION. Требует wal_level = logical. Можно реплицировать часть таблиц между разными версиями и схемами.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки