Вступить в клуб →
средняявопросPostgreSQL и Redis: запросы и кэш

HTTP-вызов внешнего провайдера внутри открытой транзакции

Обработка платежа выглядит так:

tx, _ := db.BeginTx(ctx, nil)
defer tx.Rollback()

_, _ = tx.ExecContext(ctx, `UPDATE accounts SET balance = balance - $1 WHERE id = $2`, amount, accID)

resp, err := provider.Charge(ctx, req) // внешний HTTP, обычно 300 мс, при деградации до 10 с
if err != nil {
    return err
}

_, _ = tx.ExecContext(ctx, `INSERT INTO payments (...) VALUES (...)`)
return tx.Commit()

При замедлении провайдера сервис перестаёт отвечать целиком, в логах — ожидание свободного соединения к БД. Что здесь основная причина?

  • Транзакция удерживает соединение и блокировки строки счёта всё время внешнего вызова — растут очереди и исчерпывается пул
  • Проблема снимается уровнем изоляции: на Read Committed блокировки строк не удерживаются до конца транзакции
  • Причина в `defer tx.Rollback()`: он держит транзакцию открытой даже после успешного `Commit` и не отдаёт соединение
  • Достаточно поднять `statement_timeout` на сервере БД, чтобы ожидания перестали накапливаться в очереди к пулу

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела