Mysql: Слишком много соединений

Созданный на 23 июл. 2013  ·  9Комментарии  ·  Источник: go-sql-driver/mysql

При вызове db.sqlDB.Query () появляется сообщение об ошибке «Слишком много соединений». Прежде чем я углублюсь в эту проблему, мне интересно, есть ли известная проблема.

Мысли?

013/07/23 03:05:35 yy.UpdateThingy () db.go: 264 [Не удалось вставить запись в XXXX: Ошибка 1040: Слишком много подключений]

Я использую версию 1.1.1:
go версия go1.1.1 linux / 386

Я использую версию драйвера mysql:
v1.0.1

Версия MySql:
Версия сервера: 5.5.22-0ubuntu1 (Ubuntu)

Вот пример одного из моих запросов:
строки, err =
db.sqlDB.Query ("вставить в XXXX (yyyy) значение (?)",
connect.ZZZZ)
if err! = nil {
_ = rows.Close ();
вернуть результат, ошибка
}
_ = rows.Close ();

Я добавил rows.Close (), надеясь, что это решит проблему, но без кубиков.

К вашему сведению, некоторые из моих запросов используют "rows.Scan", а некоторые нет.

question working as intended

Самый полезный комментарий

Вариант 1. Слишком высокая степень параллелизма

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

Вариант 2: негерметичные соединения

Скорее всего, ваша программа просто теряет соединения с базой данных. Это происходит, если вы не закрываете rows возвращаемое db.Query или забыли завершить транзакции (в базе данных / sql tx api ).

Мой общий совет - использовать

  • db.Exec если вы не ожидаете возвращаемой строки (другими словами, вы ничего не Scan ). После казни соединение сразу же становится свободным.
  • db.QueryRow если вы ожидаете одну строку. Если вы используете цепной синтаксис , вы не можете утечь соединения
  • db.Query если вы ожидаете несколько строк. Очень важно, чтобы вы «освободили» соединение, прочитав все возвращенные строки (цикл rows.Next ) или вызвав rows.Close . Конечно, неплохо отложить вызов rows.Close . Не забывайте об ошибках и т. Д.

Все 9 Комментарий

Взгляните сюда: https://github.com/VividCortex/go-database-sql-tutorial

Не используйте .Query, используйте .Exec.

Вариант 1. Слишком высокая степень параллелизма

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

Вариант 2: негерметичные соединения

Скорее всего, ваша программа просто теряет соединения с базой данных. Это происходит, если вы не закрываете rows возвращаемое db.Query или забыли завершить транзакции (в базе данных / sql tx api ).

Мой общий совет - использовать

  • db.Exec если вы не ожидаете возвращаемой строки (другими словами, вы ничего не Scan ). После казни соединение сразу же становится свободным.
  • db.QueryRow если вы ожидаете одну строку. Если вы используете цепной синтаксис , вы не можете утечь соединения
  • db.Query если вы ожидаете несколько строк. Очень важно, чтобы вы «освободили» соединение, прочитав все возвращенные строки (цикл rows.Next ) или вызвав rows.Close . Конечно, неплохо отложить вызов rows.Close . Не забывайте об ошибках и т. Д.

Я изменил "db.Query ()" на "db.Prepare () и db.Exec ()", и это устранило мою проблему. Спасибо за быстрые и отличные ответы.

Я тоже получил это.
и я использую "db.Prepare () и db.Exec ()",

var db * sql.DB

func getdb () * sql.DB {
db, err = sql.Open ("mysql", connArgs)
db.SetMaxIdleConns (100)
вернуть db
}

func foo (db * sql.DB) {
сделать что-нибудь .....
smint, err: = db.Prepare (....)
отложить smint.Close ()
smint.Exec (....)
}

func main () {
go func () {
db = get_db ()
отложить db.Close ()
foo (db)
} ()
}

попробуйте пойти 1.3
----- Исходное сообщение -----
От: liutaihua [email protected]
Получатель: go-sql-driver / mysql [email protected]
Тема: Re: [mysql] Слишком много соединений (# 111)
Дата: 15:43, 16 июля 2014 г.

и ... почему вы запускаете горутину в основном?
Если ваш код действительно выглядит так, main может (и, вероятно, будет) завершиться до запуска горутины, и ваша программа вообще ничего не сделает.
Просто удалите go func(){ и }() . Тебе будет лучше.

извините за мое описание, собственно, код:

func socke_server () {
для {
// accept_something_from_socket как получить
go func (some_receive) {
db = get_db ()
отложить db.Close ()
foo (db)
}
}
}

func main () {
socke_server ()
}

Но теперь я использую протокол домена Unix (' user: pwd @ unix (/tmp/mysql.sock)/'), это исправлено.

спасибо ответ

Вы тоже не должны этого делать - это может сработать, но медленно.

Поместите цикл принятия в файл main.
Преобразуйте горутину в функцию верхнего уровня.
Поместите код get_db в верхнюю часть основного файла и отложите db.Closer там (и только там).
Не открывайте и не закрывайте БД таким образом.

Попробуйте следующий код:

func handleConnection(db *sql.DB, args...interface{}) {
    // do someting.....
    // db.Exec("STATEMENT", args...)
}

func main() {
    db, err := sql.Open("mysql", connArgs)
    if err != nil {
        panic(err)
    }
    db.SetMaxIdleConns(100)
    defer db.Close()
    for {
        // accept connections and pass relevant stuff to handleConnection
        go handleConnection(db, nil)
    }
}

Спасибо, поняла.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги