Повторное использование Go/Golang sql.DB в функциях

sql.Open() возвращает переменную типа *sql.DB

У меня есть функция, которая вызывает 10 других функций, которые все должны выполнять вызовы базы данных.

Является ли более правильным/эффективным:

  • Отправьте указатель *sql.DB на каждую функцию или
  • Создайте новый объект *sql.DB в каждой функции.

Значение

func DoLotsOfThings() {
    db, _ := sql.Open()
    defer db.Close()
    DoTask1(db)
    DoTask2(db)
}

or

func DoLotsOfThings() {
    DoTask1()
    DoTask2()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

Причина, по которой я спрашиваю, заключается в том, что в настоящее время я отправляю указатель на каждую функцию, и мой драйвер, похоже, ломается. Я использую http://code.google.com/p/odbc , что наводит меня на мысль, что каждая функция должна есть своя, и что я могу положиться на водительское нутро.

ИЗМЕНИТЬ

Поломка драйвера RE, это происходит только в условиях высокой нагрузки. И это происходит только после, скажем, десяти минут или около того времени. Это наводит меня на мысль, что существует какая-то утечка памяти, из-за которой использование драйвера перестает работать. Однако я откладываю db.Close() для каждого экземпляра *sql.DB, поэтому я не знаю, что еще я могу сделать, чтобы решить эту проблему.

andybalholm говорит, что пул соединений обрабатывается внутри, что кажется точным, потому что он прерывается только после того, как я пытаюсь что-то выполнить, а не когда я вызываю sql.Open()

Если я оставлю свое приложение Go запущенным, оно не сможет выполнять какие-либо SQL-запросы, но если я попытаюсь запустить другие тесты Go отдельно, подключившись к MSSQL и выполняя запросы, это сработает.


person Allison A    schedule 14.11.2013    source источник
comment
Если вы можете опубликовать воспроизводимый пример здесь code.google.com/p/odbc/issues/ list, постараюсь исправить.   -  person alex    schedule 15.11.2013


Ответы (2)


Вам не нужно открывать подключения к базе данных повсюду. Пакет database/sql создает внутренний пул соединений, открывая и закрывая соединения по мере необходимости, создавая при этом иллюзию единого соединения, которое можно использовать одновременно.

Вероятно, вам нужно искать причину поломки вашего драйвера в другом месте. Некоторые подробности об этом облегчат людям понимание того, что происходит.

person andybalholm    schedule 14.11.2013
comment
Так что у меня должна быть одна ссылка на sql.Open и результирующий *sql.DB. Кажется, вы правы насчет пула, я получаю ошибки только при попытке выполнить запрос. Как ни странно, мое приложение go перестает подключаться к MSSQL, но вне его я могу запускать тесты, которые могут подключаться, если я не запускаю хранимые процедуры. Это все очень странно. - person Allison A; 15.11.2013
comment
Одна вещь, которую следует помнить при попытке отладки приложений базы данных/sql, заключается в том, что из-за пула соединений ошибки соединения часто не отображаются, когда вы выполняете sql.Open; они ждут, пока вы не запустите первый запрос в соединении. - person andybalholm; 15.11.2013

Объявите var db *sql.DB глобально, а затем повторно используйте его в своем коде. Вот пример (упрощенный):

var db *sql.DB

func DoLotsOfThings() {
    DoTask1(db)
    DoTask2(db)
}

func main() {
  db, _ = sql.Open() # or whatever you use
  defer db.Close()
  DoLotsOfThings()
}

Глобальное объявление *sql.DB также имеет некоторые дополнительные преимущества, такие как SetMaxIdleConns (регулирует размер пула соединений ) или подготовку операторов SQL в вашем приложении.

person Kavu    schedule 14.11.2013
comment
Спасибо за эту заметку! - person Anatoly; 04.10.2014