Базы Данных (Data Base) | SQL & NoSQL. PostgreSQL, MySQL и Big Data. Уроки для Backend и Data Engineer. Архитектура БД, Оптимизация и Design.
IT и технологии · 8 июля 2026 г.
🔒 Почему одна "невинная" транзакция может положить продакшн — 8 июля 2026 г. в 15:30:43
🔒 Почему одна "невинная" транзакция может положить продакшн Классическая ситуация: разработчик открывает транзакцию, делает выборку, потом какой-то API-запрос наружу (например, к платёжному шлюзу), и только потом коммитит. Транзакция висит открытой 3-5 секунд вместо миллисекунд. Локально всё ок, тесты зелёные. В проде — деградация через пару часов. Что происходит под капотом в PostgreSQL (MVCC): 1. VACUUM не может убрать мёртвые строки. Пока жива хоть одна старая транзакция, движок обязан хранить все версии строк, которые теоретически могут быть видны в её snapshot. UPDATE/DELETE копится в виде dead tuples, автовакуум работает, но эффективность падает. 2. Table bloat. Таблица физически растёт, индексы разбухают, страницы всё реже помещаются в shared_buffers — растёт I/O, падает cache hit ratio. 3. xmin horizon не двигается. Это глобальная граница, до которой можно чистить старые версии. Одна зависшая транзакция держит её на месте для ВСЕЙ базы, а не только для своей таблицы. 4. Реплики страдают отдельно. На hot standby с hot_standby_feedback = on долгая транзакция на реплике заставляет primary тоже не вакуумить нужные строки — эффект расползается по кластеру. Как ловить: SELECT pid, now() - xact_start AS duration, query FROM pg_stat_activity WHERE state != 'idle' ORDER BY duration DESC LIMIT 10; Плюс idle in transaction — отдельная категория боли: транзакция открыта, а коннекшен вообще ничего не делает (забыли закоммитить/роллбэкнуть). Лечится через idle_in_transaction_session_timeout. Правило для сеньора: транзакция должна жить ровно столько, сколько нужно для консистентности данных — не больше. Любой сетевой вызов, любая тяжёлая бизнес-логика — только вне транзакции или в отдельном коротком шаге. #postgresql #databases #mvcc #db 👉 @database_info