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.
Bitte schauen Sie hier: https://github.com/VividCortex/go-database-sql-tutorial
Verwenden Sie nicht .Query, sondern .Exec.
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.
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 verlierendb.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.
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 vondb.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, SieScan
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 verlierendb.Query
wenn Sie mehrere Zeilen erwarten. Es ist sehr wichtig, dass Sie die Verbindung "freigeben", indem Sie entweder alle zurückgegebenen Zeilen lesen (Schleiferows.Next
) oderrows.Close
aufrufen. Natürlich ist es eine gute Idee, einen Anruf vonrows.Close
aufzuschieben. Vergessen Sie nicht die Fehlerfälle usw.