Ответ
В Go для отслеживания и обработки ошибок соединения с БД используется комбинация нескольких подходов, так как пакет database/sql абстрагирует пул соединений.
-
Проверка при инициализации (
sql.Open)sql.Openне устанавливает соединение с БД, а лишь подготавливает структуру*sql.DB. Ошибка на этом этапе означает неверные параметры (например, неправильный DSN или несуществующий драйвер).db, err := sql.Open("postgres", "user=... password=... ...") if err != nil { // Ошибка конфигурации, а не сети log.Fatalf("Invalid DB config: %v", err) } -
Проверка реального соединения (
db.PingContext) Это основной способ проверить, что соединение с базой данных может быть установлено. Его вызывают сразу послеsql.Open.ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := db.PingContext(ctx); err != nil { log.Fatalf("DB connection failed: %v", err) } -
Обработка ошибок при выполнении запросов Любой вызов (
QueryContext,ExecContext,BeginTx) может вернуть ошибку, связанную с потерей соединения. Пакетdatabase/sqlпытается автоматически переподключиться при некоторых временных ошибках, но если это не удается, ошибка будет возвращена приложению.rows, err := db.QueryContext(ctx, "SELECT id FROM users") if err != nil { // Здесь может быть ошибка сети, таймаут или другая проблема с соединением log.Printf("Query failed: %v", err) // Здесь можно реализовать логику повторных попыток (retry) return } -
Реализация логики повторных попыток (Retry) Для временных сбоев сети полезно реализовать механизм
retryс экспоненциальной выдержкой (exponential backoff), чтобы не перегружать БД запросами на переподключение.// Псевдокод for i := 0; i < maxRetries; i++ { err = db.Ping() if err == nil { break // Успешно } // Ожидаем (1s, 2s, 4s, ...) time.Sleep(time.Second * (1 << i)) } -
Мониторинг состояния пула соединений
*sql.DBпредоставляет статистику пула, которая помогает отслеживать его здоровье.stats := db.Stats() // stats.OpenConnections - количество открытых соединений // stats.WaitCount - сколько раз запросы ждали свободного соединения // stats.WaitDuration - общее время ожиданияЭти метрики полезно экспортировать в систему мониторинга (Prometheus, Grafana) для долгосрочного анализа.