Mysql: Seltsamer Fehler bei unterbrochener Verbindung

Erstellt am 5. Dez. 2013  ·  25Kommentare  ·  Quelle: go-sql-driver/mysql

Wenn ich Verbindungen mit lang laufenden Abfragen beende, erhalte ich Folgendes:

[MySQL] 2013/12/05 22:17:19 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:19 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:27 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:27 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:39 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:39 statement.go:24: Invalid Connection

Ich bin es gewohnt, diesen Fehler zu sehen:

2013 (HY000) at line 1: Lost connection to MySQL server during query

Soweit ich weiß, wird dieser Fehler tatsächlich über die Netzwerkverbindung an den Client zurückgesendet, der getötet wurde. Wird dies im Treiber oder in der Datenbank / SQL maskiert oder handelt es sich nicht, wie ich denke, um einen Fehler, der über das Protokoll übertragen wird? Können wir klarer machen, was irgendwie passiert?

bug thinking

Hilfreichster Kommentar

Ich denke das ist das Problem:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Alle 25 Kommentare

Nein, es wird kein Fehler übertragen. Der Fehler ist eigentlich, dass nichts empfangen werden kann: wink:
Es ist jedoch möglicherweise eine gute Idee, eine aussagekräftigere Fehlermeldung als EOF zu drucken

Ich denke, die statement.go:24: Invalid Connection Fehler sind ein Ergebnis von http://golang.org/issue/5718
Diese Fehler sollten verschwinden, wenn die Logik für die automatische Wiederverbindung im Datenbank- / SQL-Paket behoben ist.

EOF ist nur io.EOF , ich bin mir nicht sicher, ob wir dies filtern und ersetzen sollen. Es ist eine Art Go-Redewendung, es für Fälle wie diesen zu verwenden (wie z. B. im Netzpaket, aus dem dieser Fehler stammt). Aber zumindest sollte die Bedeutung irgendwo dokumentiert werden.

Was ist deine Meinung?

Ich würde gerne hören, was @gkristic auch davon hält. Er hat es studiert.

Ich folgte dem Code bei database / sql. Die statement.go:24: Invalid Connection -Fehler sind kein Ergebnis von http://golang.org/issue/5718 , obwohl ich @julienschmidt darin Query() und Exec() , wenn diese auf DB-Ebene ausgeführt werden, aber keine, wenn Sie einen Stmt-Empfänger verwenden.

Die @ xaprb- Säge "Ungültige Verbindung" ist darauf zurückzuführen, dass die MySQL-Verbindung nicht mehr verfügbar ist, wenn Close() für eine vorbereitete Anweisung aufgerufen wird, dh stmt.mc.netConn ist hier gleich Null. Es ist eine harmlose Nachricht, da die Verbindung bei database / sql geschlossen wird, sobald ErrBadConn zurückgegeben wird.

Aber das ist nicht die einzige Möglichkeit, die ich gesehen habe. database / sql (Go 1.2) weist möglicherweise einige Parallelitätsprobleme auf, die möglicherweise auch zu dieser Nachricht führen. Wenn eine (Datenbank / SQL) -Anweisung geschlossen wird, während eine Treiberverbindung sie verwendet, soll die Treiberanweisung beim nächsten putConn() um noteUnusedDriverStatement() . Aber putConn() könnte laufen, bevor removeOpenStmt() aufgerufen wird (siehe (*Stmt) finalClose() ). Wenn nach dem Aufruf ausstehender onPut -Funktionen die Verbindung selbst aufgrund des Leerlaufverbindungslimits geschlossen wird, versucht das Paket, die Anweisung erneut zu schließen, was zur Meldung führt. Das ist wieder harmlos, aber trotzdem nervig.

Die Datenbank / SQL von IMHO Go muss sorgfältig überarbeitet werden ...

@gkristic Schlagen Sie Änderungen im Treiber vor?

Das Datenbank- / SQL-Paket weist einige Mängel auf. Ich hoffe, einige Verbesserungen für Go 1.3 vornehmen zu können. Die Überprüfung des Abhängigkeitsmanagements ist ein Punkt auf meiner Liste.

Wenn Sie solche Probleme entdecken, melden Sie diese bitte unter https://code.google.com/p/go/issues/list.

Angesichts der Tatsache, dass diese Bedingungen (dh Verbindungsverlust oder doppeltes Schließen durch Datenbank / SQL) harmlos sind, würde ich erwarten, dass der Treiber diese stillschweigend überspringt, anstatt die Nachricht "Ungültige Verbindung" zu drucken. Meiner Meinung nach kann das letztere entweder sein: beängstigend, wenn Sie nicht wissen, dass es harmlos ist; ärgerlich, wenn Sie es einmal tun; aber möglicherweise irreführend, wenn eine identische Nachricht an einer anderen Stelle gedruckt wird (und abgesehen von der Zeilennummer) und eine echte Warnung verbirgt, die Sie leicht überspringen könnten. Wenn entweder stmt.mc oder stmt.mc.netConn bei der Anweisungsfunktion Close() Null sind, würde ich eine Rückgabe ohne weitere Protokollierung bevorzugen. Beachten Sie außerdem, dass die Rückgabe von driver.ErrBadConn dort (wie unter 4d3764bbcb17c31575642626baeab1bcdc30c301 eingeführt) absolut keine Auswirkungen hat, da database / sql den Rückkehrcode niemals auf eine geschlossene Anweisung überprüft.

Als Randnotiz würde ich wahrscheinlich eine Funktion hinzufügen, um den Logger zu optimieren. Derzeit ist errLog im Paket initialisiert und privat. Es wird nach einem Standardfehler gedruckt, der möglicherweise verfügbar ist oder nicht. Das heißt, ein Prozess kann sich aus anderen Gründen dafür entscheiden, den Deskriptor zu schließen. Aber selbst wenn dies nicht der Fall ist, hat der Benutzer möglicherweise eine andere Vorstellung von der Protokollierung (denken Sie an Dateien, Syslog usw.). Der Treiber könnte diesen Standardlogger bereitstellen, dem Benutzer aber möglicherweise auch erlauben, einen anderen festzulegen.

Sobald ich etwas Freizeit habe, werde ich ein kleines Beispiel für das zuvor erwähnte Problem vorbereiten und einen Bericht schreiben.

Vielen Dank!

@gkristic in Bezug auf den Logger - Sie meinen so etwas wie https://github.com/go-sql-driver/mysql/pull/182 (vor einer Woche in master zusammengeführt)?

@arnehormann Oh Mann ... genau das. Ich habe mit v1.1 gearbeitet. Ich habe vor dem Posten auch die anderen Dinge beim Master überprüft, aber vergessen, die Protokollierung zu überprüfen. Entschuldigung und danke!

@gkristic überhaupt kein Problem: grinsend:

Irgendwelche Änderungen, die vor der nächsten Veröffentlichung vorgenommen werden sollten? PRs willkommen :)

Hey Leute, neuer Benutzer des go-sql-Treibers hier. Ich habe ähnliche Probleme bemerkt, habe mich aber gefragt, ob mir jemand helfen könnte, zu bestätigen, dass die Ursache dieselbe ist? Bei lang laufenden Crones, die Goroutinen verwenden, erhalte ich routinemäßig Folgendes.

[MySQL] 2014/05/14 20:33:05 packets.go:356: Busy buffer
[MySQL] 2014/05/14 20:33:05 packets.go:73: EOF
[MySQL] 2014/05/14 20:33:05 statement.go:24: Invalid Connection
[MySQL] 2014/05/14 20:33:05 connection.go:206: Invalid Connection

Ich bin mehr als bereit, mir hier die Hände schmutzig zu machen, und suche nur nach einer Anleitung, wie ich das Problem angehen kann. Ist dieser Fehler "Ungültige Verbindung" unter bestimmten Umständen sicher zu ignorieren? Gibt es eine Möglichkeit, automatisch eine andere Verbindung herzustellen, wenn dies erkannt wird?

Oh, oh ... jetzt wo ich sehe, habe ich den Kommentar von @julienschmidt vom letzten Freitag verpasst. (Ich entschuldige mich bei Julien.) @Rmulley , es sieht so aus, als hätten Sie das gleiche Problem, das ich oben beschrieben habe. Schau dir diesen Kommentar an. Die "Ungültige Verbindung" bei statement.go: 24 ist harmlos. Der Treiber sollte das Richtige tun, indem er eine andere Verbindung wählt. Ich bin mir jedoch nicht sicher über den "Busy Buffer". Ich kann mich nicht erinnern, das gesehen zu haben. Es ist schon eine Weile her, seit ich diesen Code überprüft habe. Ich werde etwas Zeit einplanen, um es mir noch einmal anzusehen und zu sehen, ob ich helfen kann. Das kann leider nicht vor Ende nächster Woche passieren. Aber bis dahin melde ich mich wieder bei Ihnen.

@rmulley : Für mich scheint dies nichts mit diesem Problem zu
Bitte versuchen Sie, diesen Fehler mit der aktuellen Git-Master-Version zu reproduzieren, falls Sie eine Version verwendet haben, die von go get installiert wurde (dies ist eine ältere Version).
Bitte öffnen Sie dann eine neue Ausgabe. Ein minimales Codebeispiel, das diesen Fehler auslöst, würde definitiv helfen.

Es scheint, als ob (b *buffer) takeBuffer nil zurückgibt. Dies scheint nur zu passieren, wenn b.length > 0 . Dies würde bedeuten, dass sich aus irgendeinem Grund ungelesene Daten im Puffer befinden.
Ich habe diesen Fehler noch nie gesehen und diese zusätzlichen Überprüfungen nur aus Sicherheitsgründen durchgeführt. Ich hätte diesen Fehler in freier Wildbahn nie geglaubt.

Laut # 206 verschwindet dieser Fehler tatsächlich, wenn go von der Spitze ausgeführt wird. Ist das nicht wirklich der Fall?

Zunächst einmal, entschuldigen Sie die späte Antwort, die ich im Urlaub hatte und dann vergessen habe, nachzufragen. Ich habe sichergestellt, dass ich die neueste Version des MySQL-Treibers habe und teste jetzt mit Go 1.3. Es sieht so aus, als würde ich jetzt mehr Details in der Fehlermeldung sehen.

[MySQL] 2014/06/23 11:46:04 packets.go:356: Busy buffer
[MySQL] 2014/06/23 11:46:04 packets.go:73: read tcp xxx.xxx.xxx.xx:3306: connection reset by peer

Ist das ein MySQL-Problem für mich? (Ich habe online nichts Nützliches gefunden, um dieses Problem zu beheben.)
Oder kann ich das überprüfen und dann irgendwie wieder eine Verbindung in meinem Code herstellen?

ich bin auf das gleiche problem gestoßen wie rmulley beschrieben. Was anders war, ist, dass der "Besetzt-Puffer" in einer extrem kurzen Abfrage erschien (so kurz wie 1 Abfrage + 2 Execs).

Ich glaube, das Problem hängt mit vorbereiteten Aussagen zusammen. Ich fand, dass, wenn ich eine Erklärung in einer Transaktion vorbereitet habe, wie

 stmt, err = tx.Prepare("SELECT ...")

Ich muss diesen Stmt schließen, bevor ich eine weitere Anweisung vorbereite, sonst stoße ich jedes Mal auf "Busy Buffer". wenn ich keine vorbereiteten Anweisungen verwende, zum Beispiel direkt mit tx like

 tx.Query("...")

oder

tx.Exec("...")

, es war gut.

und wenn ich eine Anweisung vorbereite und dann andere Abfragen ausführe oder andere Dinge ausführe, ist es auch in Ordnung ... bereite einfach keine weitere Anweisung vor, ohne die vorherige zu schließen, und es sieht gut aus.

Ich hoffe, es ist wirklich dort, wo das Problem liegt.

Vielen Dank.

Können Sie vielleicht ein kleines Go-Programm erstellen, mit dem der Fehler reproduziert werden kann?
Es scheint definitiv ein Fehler im Treiber zu sein, der jedoch nicht mit dem hier gemeldeten ursprünglichen Problem zusammenhängt.
Bitte erstellen Sie dann eine neue Ausgabe.

Ich denke das ist das Problem:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Ich bin gerade auf ein ähnliches Problem mit dem ausgelasteten Puffer gestoßen und kann bestätigen, dass

Hallo Leute, ich weiß nicht, ob dies in irgendeiner Weise gelöst wurde. Ich sehe dieses Problem in kurzen Einfügungen, die mit "Exec" -> ausgeführt werden

var sql = "In Tabelle (f1, f2 ... f25) Werte einfügen (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Nach ungefähr 4000, manchmal 5000 Einfügungen erhalte ich "Unexpected EOF" und "Busy Buffer".
Die Einsätze sind dicht (in einer for-Schleife), aber es gibt eine REST-Anforderung zwischen jedem, also nicht so schnelles Feuer; gleiche Verbindungsreferenz. Dies ist Go 1.3.

Vielen Dank,
Sal

@Sal - was passiert, wenn Sie go 1.4 verwenden?

Am Mittwoch, 31. Dezember 2014, um 22:11 Uhr, Sal A. Magnone [email protected]
schrieb:

Hallo Leute, ich weiß nicht, ob dies in irgendeiner Weise gelöst wurde. Ich sehe das
Ausgabe in kurzen Einfügungen mit "Exec" ->

var sql = "In Tabelle (f1, f2 ... f25) Werte einfügen (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Nach ungefähr 4000, manchmal 5000 Einsätzen bekomme ich "Unexpected EOF" und "Busy"
Puffer".
Die Einfügungen sind eng (in einer for-Schleife), aber es gibt eine REST-Anforderung zwischen
jedes also nicht so schnelles Feuer; gleiche Verbindungsreferenz. Dies ist Go 1.3.

Vielen Dank,
Sal

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

Danke für deine Antwort.

1.4 - gleicher Fehler. Gestorben bei 4205 Einsätzen in ca. 50 Minuten (zwischen jedem Einsatz befinden sich Netz- und Bildschirm-E / A).

Ich habe den Code überarbeitet, um optional dort weiterzumachen, wo er beim letzten Mal aufgehört hat. Daher nicht kritisch für diese App, könnte aber für andere Apps in diesem Projekt kritisch sein, wenn dies ein kumulatives Anforderungsproblem ist.

-Sal

Von: carbocation [mailto: [email protected]]
Gesendet: Sonntag, 4. Januar 2015, 9:50 Uhr
An: go-sql-driver / mysql
Cc: Sal A. Magnone
Betreff: Re: [mysql] Seltsamer Fehler bei unterbrochener Verbindung (# 185)

@Sal - was passiert, wenn Sie go 1.4 verwenden?

Am Mittwoch, 31. Dezember 2014, um 22:11 Uhr, Sal A. Magnone < [email protected] [email protected] >
schrieb:

Hallo Leute, ich weiß nicht, ob dies in irgendeiner Weise gelöst wurde. Ich sehe das
Ausgabe in kurzen Einfügungen mit "Exec" ->

var sql = "In Tabelle (f1, f2 ... f25) Werte einfügen (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Nach ungefähr 4000, manchmal 5000 Einsätzen bekomme ich "Unexpected EOF" und "Busy"
Puffer".
Die Einfügungen sind eng (in einer for-Schleife), aber es gibt eine REST-Anforderung zwischen
jedes also nicht so schnelles Feuer; gleiche Verbindungsreferenz. Dies ist Go 1.3.

Vielen Dank,
Sal

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

- -
Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68635254 an. https://github.com/notifications/beacon/AA4DdvfCFMdiqPlTZITEs9VrxyyJqqFQks5neUqigaJpZM4BSM1b.gif

Verwandelt sich dieser Thread jetzt in ein paar Threads? Sollten die neuesten Kommentare in eine neue Ausgabe aufgenommen und diese geschlossen werden?

@xaprb Ich stimme zu, ich denke, es gibt ein paar Threads, die gerade laufen. Wir können diesen wahrscheinlich schließen und von https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413 in eine neue Ausgabe übernehmen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen