Как ответить
Двухстадийная фиксация (2PC) — это протокол для обеспечения атомарности распределённых транзакций. Он используется, когда нужно согласованно изменить данные на нескольких независимых узлах (разные СУБД, очереди, сервисы). Протокол состоит из двух фаз: Prepare (голосование) и Commit/Abort (завершение).
Работает так. Есть координатор (transaction manager) и несколько участников. Когда приложение хочет зафиксировать транзакцию:
- Фаза 1 (Prepare). Координатор отправляет всем участникам запрос «готов ли ты к коммиту?». Каждый участник проверяет, может ли он выполнить транзакцию, фиксирует своё состояние как prepared (но не коммитит), блокирует затронутые ресурсы и отвечает Yes или No. Ответ Yes — это обещание, что участник сможет закоммититься даже при последующем отказе.
- Фаза 2 (Commit/Abort). Если все ответили Yes, координатор записывает решение Commit в свой лог и рассылает команду Commit всем участникам. Те применяют изменения и отпускают блокировки. Если хотя бы один ответил No или не ответил за таймаут, координатор записывает Abort и все участники откатывают prepared-состояние.
Протокол реализован в спецификации X/Open XA (JTA, .NET TransactionScope), в PostgreSQL через команды PREPARE TRANSACTION и COMMIT PREPARED, в Oracle RAC. Пример — перевод денег между двумя разными БД: дебет в одной, кредит в другой — нужно либо оба успеха, либо откат обоих.
Основные проблемы 2PC:
- Блокировки. Во время фазы Prepare участники держат блокировки на изменяемые строки или таблицы. Если координатор падает, блокировки висят до его восстановления — это снижает параллелизм.
- Синхронность. Все участники должны быть доступны. Задержка одного тормозит всю транзакцию.
- Единая точка отказа. Отказ координатора в критический момент (после решения Commit, но до рассылки) может привести к неопределённому состоянию. Для восстановления нужен анализ логов координатора и, возможно, ручное вмешательство.
Из-за этих ограничений 2PC редко используют в микросервисных архитектурах. Вместо него применяют паттерны Saga (цепочка локальных транзакций с компенсирующими действиями) или TCC (Try-Confirm/Cancel). Но для систем, требующих строгой согласованности и имеющих единый менеджер транзакций (например, в legacy банкинге), 2PC остаётся рабочим стандартом.