pool_pre_ping включён, транзакция упала: границы проверки соединения

После перезапуска PostgreSQL первый запрос иногда получает ошибку старого соединения. Разработчик включает pool_pre_ping, и этот симптом исчезает. Позже сеть обрывается уже во время оформления заказа, и запрос снова падает. Настройка не перестала работать: она проверяет соединение в определённый момент, а не сопровождает транзакцию непрерывной страховкой.

Pre-ping нужен при выдаче соединения из пула. Если оно стало непригодным во время простоя, проверка позволяет заменить его до обычной работы. Но соединение может оборваться после успешной проверки: между первым и вторым SQL-запросом или во время commit. Проверка прошлого состояния не делает будущую сетевую операцию безотказной.

Разделить checkout и транзакцию

Для синхронного SQLAlchemy Engine с PostgreSQL настройка передаётся при создании. Требуются SQLAlchemy и выбранный DBAPI-драйвер; для этого URL используется psycopg. Установка: python -m pip install 'SQLAlchemy>=2,<3' 'psycopg[binary]>=3,<4'.

import os
from sqlalchemy import create_engine, text

engine = create_engine(os.environ['DATABASE_URL'], pool_pre_ping=True)

with engine.begin() as connection:
    connection.execute(text('SELECT 1'))

DATABASE_URL должен иметь форму postgresql+psycopg:// с параметрами вашего тестового сервера. Контекст engine.begin открывает область транзакции и завершает её при выходе. Он не означает автоматическое повторение всех действий после разрыва. Если исключение вышло из блока, код вызова должен решить, что сообщить клиенту и можно ли начать новую попытку.

Для заказа повторение последнего INSERT недостаточно: до него могли быть другие изменения. Если повтор допустим, восстанавливают всю логическую транзакцию с начала. Кроме того, рядом могли выполняться внешние действия — отправка письма или запрос в платёжную систему. Повтор SQL не откатывает уже отправленное письмо. Границу повторения нужно проектировать на уровне операции с её идентификатором и контролем дублей.

Проверить два разных отказа

На отдельной базе сначала создайте соединение, верните его в пул и разорвите именно этот серверный сеанс. Следующее получение соединения проверяет сценарий, для которого включён pre-ping. Затем в другой проверке оборвите соединение после начала транзакции. Теперь исключение должно дойти до приложения, а незавершённая операция — остаться явно неуспешной.

Особенно осторожно разбирайте потерю связи вокруг commit: клиент может не знать, успел ли сервер зафиксировать изменения до разрыва. Механический повтор способен создать дубль. Поэтому полезен уникальный идентификатор бизнес-операции и возможность проверить её итоговое состояние на новом соединении. Это свойство схемы и приложения, а не параметр пула.

В журнале отделяйте получение соединения, начало операции и её финальный результат. Не записывайте пароль из URL. После такой разметки pool_pre_ping занимает понятное место: он уменьшает использование протухших соединений при checkout, а обработка отказа внутри транзакции остаётся явной частью кода сервиса.

Продолжить практику

Такие ошибки становятся понятнее, когда жизненный цикл ресурсов и обработка исключений выражены в коде явно. В курсе «Python для профессионалов» есть практика контекстных менеджеров, декораторов, асинхронного кода и профилирования. Это продолжение для разработчика, который уже пишет сервисы и хочет увереннее управлять выполнением Python-программы: ограничивать область работы с ресурсом, понимать завершение операции и находить причину лишнего ожидания. Выберите в программе темы, которые нужны вашему следующему проекту.

Посмотреть программу курса

Источник: официальная документация.

Другие задачи по теме: База, HTTP-клиенты и тесты API.

Продолжить на практике

  • Python для профессионалов ↗

    Python для профессионалов — курс для людей, стремящихся углубить свои знания языка. Вы изучите итераторы, генераторы, декораторы, современные возможности Python (3.8+), освоите метапрограммирование, асинхронность, внутреннее устройство интерпретатора, инструменты оптимизации и профилирования, а также получите уверенность в использовании продвинутых возможностей стандартной библиотеки.