web-dev-qa-db-fra.com

Golang, mysql: Erreur 1040: Trop de connexions

J'utilise le pilote github.com/go-sql-driver/mysql pour aller.

J'ouvre une base de données:

db, err := sql.Open("mysql", str)

Ensuite, j'ai deux fonctions qui sont appelées 200 fois chacune avec le code mysql suivant:

rows, err := db.Query("select name from beehives")
if err != nil {
    panic(err)
}       
defer rows.Close()

La deuxième:

    err = db.QueryRow("select id, secret, shortname from beehives where shortname = ?", beehive).Scan(&id, &secre
    switch {
    case err == sql.ErrNoRows:
        err = errors.New("Beehive '"+beehive+"' not found.")
    case err != nil:
        panic("loginBeehive: "+ err.Error())
    default:
        // ... do the work

Le premier panique.

Comment peut-il y avoir plusieurs connexions lorsque j'ouvre la base de données une seule fois et comment les fermer?

22
Michael

sql.Open n'ouvre pas vraiment une connexion à votre base de données.

Un sql.DB gère un pool de connexions à votre base de données. Chaque fois que vous interrogez votre base de données, votre programme essaiera d'obtenir une connexion à partir de ce pool ou d'en créer une nouvelle dans le cas contraire. Ces connexions sont ensuite remises dans la piscine une fois que vous les avez fermées.

C'est ce que fait rows.Close(). Votre db.QueryRow("...") fait la même chose en interne lorsque vous appelez Scan(...).

Le problème de base est que vous créez trop de requêtes, dont chacune a besoin d'une connexion, mais vous ne fermez pas vos connexions assez rapidement. De cette façon, votre programme doit créer une nouvelle connexion pour chaque requête.

Vous pouvez limiter le nombre maximum de connexions que votre programme utilise en appelant SetMaxOpenConns sur votre sql.DB.

Voir http://go-database-sql.org/surprises.html pour plus d'informations.

26
nussjustin

Le *DB objet que vous récupérez de sql.Open ne correspond pas à une connexion unique . Il est préférable de le considérer comme un handle pour la base de données: il gère un pool de connexions pour vous.

Vous pouvez contrôler le nombre de connexions ouvertes avec `(* (DB) .SetMaxOpenConns et sa paire pour les connexions inactives.

Donc, fondamentalement, ce qui se passe ici est que db.Query et db.QueryRow essaie d'acquérir une connexion pour eux-mêmes et le handle de base de données ne met aucune restriction sur le nombre de connexions simultanées, donc votre code panique lorsqu'il s'ouvre plus que ce que mysql peut gérer.

6
tmichel

Essayez de faire des instructions préparées db.Prepare(query string) (*Stmt, error) et que stmt.Query ou stmt.Exec et que stmt.Close pour réutiliser les connexions.

3
Uvelichitel