Зміст
Коротко
На GitHub колись пала база не через злом, а через одну незакриту транзакцію: міграція чекала на ексклюзивне блокування, нові запити ставали в чергу — і все «зависло», доки інженер не знайшов проблемне з'єднання. Той самий сценарій легко відтворити в Postgres: необроблений виняток у застосунку лишає транзакцію відкритою, міграція блокується, гаряча таблиця перестає відповідати.
Що сталося
Класичний сценарій у MySQL: зміна схеми потребує ексклюзивного блокування таблиці, але інша сесія вже читала таблицю і не зробила COMMIT. Міграція чекає. За нею — усі нові запити до тієї ж таблиці. Ні deadlock, ні таймаут самі не рятують: ланцюжок сидить, доки не завершать проблемне з'єднання.
У Postgres достатньо звичайного користувача застосунку. Транзакція починає SELECT по гарячій таблиці orders, застосунок падає з винятком — ROLLBACK не викликається. Сесія «в транзакції», хоча запит уже завершився. Паралельно міграція робить ALTER TABLE і чекає ACCESS EXCLUSIVE. Усі наступні SELECT стають у чергу. Для сервісу, що очікує швидких відповідей з orders, це простій.
Часта причина — налаштування за замовчуванням: idle_in_transaction_session_timeout вимкнено — «висячі» транзакції не обриваються самі.
PlanetScale описує інструменти перегляду та завершення з'єднань у панелі та CLI (pscale branch connections), навіть коли слоти підключень вичерпано.
Чому це важливо
Це не рідкий edge case і не прерогатива MySQL. Будь-яка СУБД з блокуваннями на рівні таблиці/схеми вразлива до «одного поганого з'єднання». Симптоми виглядають як повна відмова, а корінь — одна сесія без COMMIT/ROLLBACK.
На співбесідах цей кейс GitHub використовували як перевірку системного мислення DBA. У проді його ловлять пейджингом у п'ятницю ввечері.
На практиці
- У Postgres задайте
idle_in_transaction_session_timeout— транзакції без активності закриються автоматично. - У коді застосунку: при будь-якому винятку всередині транзакції — явний ROLLBACK або закриття з'єднання через пул.
- Міграції на гарячих таблицях плануйте з урахуванням блокувань; для MySQL на Vitess/PlanetScale онлайн-ALTER знижує ризик довгого ексклюзивного блокування.
- Майте спосіб дивитися активні сесії та «хто кого блокує» до інциденту.
- При розборі інциденту розрізняйте: скасувати запит, завершити транзакцію, обірвати з'єднання — для «завислого» SELECT часто потрібен terminate transaction або terminate connection.
Підсумок
Падіння бази через одне необроблене виключення — урок про межі застосунку та СУБД. Таймаути idle-транзакцій, дисципліна ROLLBACK і огляд з'єднань коштують дешевше, ніж година простою гарячої таблиці.

