Mysql: zu viele Verbindungen

Erstellt am 23. Juli 2013  ·  9Kommentare  ·  Quelle: go-sql-driver/mysql

Beim Aufruf von db.sqlDB.Query () wird die Fehlermeldung "Zu viele Verbindungen" angezeigt. Bevor ich mich weiter mit diesem Problem befasse, frage ich mich, ob es ein bekanntes Problem gibt.

Gedanken?

013/07/23 03:05:35 yy.UpdateThingy () db.go: 264 [Fehler beim Einfügen des Datensatzes in XXXX: Fehler 1040: Zu viele Verbindungen]

Ich benutze go Version 1.1.1:
go version go1.1.1 linux / 386

Ich verwende die MySQL-Treiberversion:
v1.0.1

MySQL-Version:
Serverversion: 5.5.22-0ubuntu1 (Ubuntu)

Hier ist ein Beispiel einer meiner Fragen:
Zeilen, err =
db.sqlDB.Query ("In XXXX (JJJJ) Wert einfügen (?)",
connect.ZZZZ)
wenn err! = nil {
_ = rows.Close ();
Ergebnis zurückgeben, err
}}
_ = rows.Close ();

Ich habe "rows.Close ()" hinzugefügt, in der Hoffnung, das Problem zu beheben, aber keine Würfel.

Zu Ihrer Information, einige meiner Abfragen verwenden "rows.Scan" und andere nicht.

question working as intended

Hilfreichster Kommentar

Option 1: Zu hohe Parallelität

Sie haben zu viele gleichzeitige Datenbankzugriffe. In diesem Fall müssen Sie die Anzahl der gleichzeitigen Verbindungen manuell begrenzen, bis das Datenbank- / SQL-Paket in einer zukünftigen Version einen Blockierungsmechanismus dafür bereitstellt. In vielen Fällen wäre Caching / asynchrone Updates jedoch die bessere Alternative.

Option 2: Undichte Verbindungen

Höchstwahrscheinlich verliert Ihr Programm nur Datenbankverbindungen. Dies geschieht , wenn Sie nicht nahe dem rows zurück von db.Query oder vergessen haben , Transaktionen zu beenden (in Datenbank / SQL ist tx api ).

Mein allgemeiner Rat ist zu verwenden

  • db.Exec wenn Sie keine zurückgegebene Zeile erwarten (mit anderen Worten, Sie Scan nichts). Die Verbindung ist sofort nach der Ausführung frei.
  • db.QueryRow wenn Sie eine Zeile erwarten. Wenn Sie die verkettete Syntax verwenden , können Sie keine Verbindungen verlieren
  • db.Query wenn Sie mehrere Zeilen erwarten. Es ist sehr wichtig, dass Sie die Verbindung "freigeben", indem Sie entweder alle zurückgegebenen Zeilen lesen (Schleife rows.Next ) oder rows.Close aufrufen. Natürlich ist es eine gute Idee, einen Anruf von rows.Close aufzuschieben. Vergessen Sie nicht die Fehlerfälle usw.

Alle 9 Kommentare

Bitte schauen Sie hier: https://github.com/VividCortex/go-database-sql-tutorial

Verwenden Sie nicht .Query, sondern .Exec.

Option 1: Zu hohe Parallelität

Sie haben zu viele gleichzeitige Datenbankzugriffe. In diesem Fall müssen Sie die Anzahl der gleichzeitigen Verbindungen manuell begrenzen, bis das Datenbank- / SQL-Paket in einer zukünftigen Version einen Blockierungsmechanismus dafür bereitstellt. In vielen Fällen wäre Caching / asynchrone Updates jedoch die bessere Alternative.

Option 2: Undichte Verbindungen

Höchstwahrscheinlich verliert Ihr Programm nur Datenbankverbindungen. Dies geschieht , wenn Sie nicht nahe dem rows zurück von db.Query oder vergessen haben , Transaktionen zu beenden (in Datenbank / SQL ist tx api ).

Mein allgemeiner Rat ist zu verwenden

  • db.Exec wenn Sie keine zurückgegebene Zeile erwarten (mit anderen Worten, Sie Scan nichts). Die Verbindung ist sofort nach der Ausführung frei.
  • db.QueryRow wenn Sie eine Zeile erwarten. Wenn Sie die verkettete Syntax verwenden , können Sie keine Verbindungen verlieren
  • db.Query wenn Sie mehrere Zeilen erwarten. Es ist sehr wichtig, dass Sie die Verbindung "freigeben", indem Sie entweder alle zurückgegebenen Zeilen lesen (Schleife rows.Next ) oder rows.Close aufrufen. Natürlich ist es eine gute Idee, einen Anruf von rows.Close aufzuschieben. Vergessen Sie nicht die Fehlerfälle usw.

Ich habe "db.Query ()" in "db.Prepare () und db.Exec ()" geändert und dadurch mein Problem behoben. Danke für die schnellen, tollen Antworten.

Ich habe das auch.
und ich benutze "db.Prepare () und db.Exec ()",

var db * sql.DB

func getdb () * sql.DB {
db, err = sql.Open ("mysql", connArgs)
db.SetMaxIdleConns (100)
return db
}}

func foo (db * sql.DB) {
etwas tun .....
smint, err: = db.Prepare (....)
verschiebe smint.Close ()
smint.Exec (....)
}}

func main () {
go func () {
db = get_db ()
aufschieben db.Close ()
foo (db)
} ()
}}

versuchen Sie es mit 1.3
----- Die ursprüngliche Nachricht -----
Von: liutaihua [email protected]
Empfänger: go-sql-driver / mysql [email protected]
Betreff: Re: [mysql] Zu viele Verbindungen (# 111)
Datum: 15:43, 16. Juli 2014

und ... warum startest du eine Goroutine in der Hauptsache?
Wenn Ihr Code wirklich so aussieht, wird (und wird wahrscheinlich) main beendet, bevor die Goroutine ausgeführt wird, und Ihr Programm wird überhaupt nichts tun.
Entfernen Sie einfach die go func(){ und }() . Du wirst besser dran sein.

Entschuldigung für meine Beschreibung, eigentlich Code:

func socke_server () {
zum {
// akzeptiere_something_from_socket als empfangen
go func (some_receive) {
db = get_db ()
aufschieben db.Close ()
foo (db)
}}
}}
}}

func main () {
socke_server ()
}}

Aber jetzt verwende ich das Unix-Domänenprotokoll (' user: pwd @ unix (/tmp/mysql.sock)/'), es wurde behoben.

danke antwort

Sie sollten das auch nicht tun - es mag funktionieren, aber es ist langsam.

Setzen Sie die Accept-Schleife in main.
Konvertieren Sie die Goroutine in eine Funktion der obersten Ebene.
Fügen Sie Ihren get_db-Code oben in Ihr main ein und verschieben Sie db.Closer auch dort (und nur dort).
Öffnen und schließen Sie die Datenbank nicht so.

Versuchen Sie den folgenden Code:

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)
    }
}

Danke, ich habe es.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen