Как проверить взаимодействие с базой данных Postgres и какие бывают проблемы?
Что проверяют
Умеете ли вы тестировать работу с базой на настоящем Postgres и знаете ли, какие проблемы вылезают только под нагрузкой. Следом обычно спрашивают, как вы нашли медленный запрос или утечку соединений на реальном проекте.
Как отвечать
Проверку разделите на уровни:
- доступность: health-check с
SELECT 1через пул, а не новое подключение на каждый запрос; - интеграционные тесты: реальный Postgres той же версии, что в проде, через testcontainers-python или сервис в CI, миграции Alembic и тесты репозиториев. Каждый тест работает в транзакции, которую фикстура pytest откатывает. SQLite вместо Postgres не годится: другие типы, нет
JSONB, иначе ведут себяON CONFLICTи блокировки; - производительность:
EXPLAIN (ANALYZE, BUFFERS)для конкретного запроса,pg_stat_statementsдля топа тяжёлых,log_min_duration_statementдля лога медленных.
Типичные проблемы:
- N+1 в SQLAlchemy: ленивая загрузка связей в цикле даёт сотни запросов, лечится
selectinloadилиjoinedload; - исчерпание соединений: по умолчанию
max_connections = 100, а каждый воркер держит свой пул; при многих процессах ставят PgBouncer; - зависшие транзакции: сессии
idle in transactionдержат блокировки и мешают vacuum, их видно вpg_stat_activity, страхуютidle_in_transaction_session_timeoutиstatement_timeout; - дедлоки: два процесса обновляют одни строки в разном порядке;
- часовые пояса:
timestampбез зоны вместоtimestamptz.
Драйвер сейчас обычно psycopg 3 или asyncpg, psycopg2 остаётся в старом коде.
Где спотыкаются
Думают, что with conn: в psycopg2 закрывает соединение. Он только завершает транзакцию коммитом или откатом. В psycopg 3 контекстный менеджер соединение закрывает.
Собирают SQL f-строкой. Значения передаются отдельно, через %s и кортеж параметров, иначе это инъекция.
Смотрят запросы на пустой базе. План на десяти строках и на десяти миллионах разный, поэтому проверяют на объёме, близком к боевому.