Mysql: 终止连接时出现奇怪的错误

创建于 2013-12-05  ·  25评论  ·  资料来源: go-sql-driver/mysql

当我终止具有长时间运行的查询的连接时,会得到如下信息:

[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

我习惯于看到此错误:

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

据我所知,该错误实际上是通过网络连接发送回被杀死的客户端的。 这是在驱动程序或数据库/ sql中被掩盖了,还是我认为不是通过协议传输的错误? 我们能以某种方式更清楚地说明正在发生什么吗?

bug thinking

最有用的评论

我认为这是问题所在:

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

所有25条评论

不,不会传输任何错误。 错误实际上是什么都收不到:wink:
但是打印比EOF更具描述性的错误消息可能是一个好主意

我猜statement.go:24: Invalid Connection错误是http://golang.org/issue/5718的结果
在数据库/ sql程序包中修复自动重新连接逻辑后,这些错误应消失。

EOF只是io.EOF ,我不确定是否应该过滤并替换它。 在这种情况下使用它是一种Go习惯用法(例如,在net程序包中,此错误源于此)。 但至少含义应记录在某处。

你怎么看?

我也想听听@gkristic对此的看法。 他一直在研究它。

我遵循了数据库/ sql中的代码。 statement.go:24: Invalid Connection错误不是http://golang.org/issue/5718的结果,尽管我同意@julienschmidt的观点,即程序包应尝试重试。 在数据库级别运行Query()Exec()调用最多可进行十次尝试,但在使用Stmt接收器时则没有尝试。

@xaprb看到的“无效连接”是由于在为准备好的语句调用Close()时,MySQL连接不再可用,即stmt.mc.netConn在这里为nil。 这是一条无害的消息,因为一旦返回ErrBadConn ,数据库/ sql的连接将被关闭。

但这不是我见过的唯一可能性; database / sql(Go 1.2)可能存在一些并发问题,也可能最终以该消息结尾。 如果在使用驱动程序连接时关闭了(database / sql)语句,则计划在noteUnusedDriverStatement()的下一个putConn()处关闭该驱动程序语句。 但是putConn()可以在调用removeOpenStmt()之前运行(请参阅(*Stmt) finalClose() )。 如果在调用挂起的onPut函数之后,由于空闲连接限制而关闭了连接本身,则程序包将尝试再次关闭该语句,从而产生消息。 这再次是无害的,但是仍然很烦人。

恕我直言Go的数据库/ sql需要仔细重新访问...

@gkristic您是否建议驱动程序进行任何更改?

数据库/ sql软件包有一些缺陷,我希望对Go 1.3进行一些改进。 重新访问依赖性管理是我列表中的一项。

如果您发现此类问题,请通过https://code.google.com/p/go/issues/list报告

鉴于这些情况(即连接丢失或数据库/ sql两次关闭)是无害的,我希望驱动程序以静默方式跳过这些情况,而不是打印“ Invalid Connection”(无效连接)消息。 我认为,后者可能是:吓人,如果您不知道那是无害的; 烦人的,一旦你做; 但如果在其他位置(行号除外)打印了相同的消息,则可能会产生误导,从而隐藏了真正的警告,您可以轻松跳过该警告。 如果stmt.mcstmt.mc.netConn在语句Close()函数中为零,我希望返回而无需进一步记录。 另外,请注意,在此处返回driver.ErrBadConn (在4d3764bbcb17c31575642626baeab1bcdc30c301中引入)绝对无效,因为数据库/ sql不会检查语句关闭的返回码。

附带说明一下,我可能会添加一个功能来调整记录器。 当前, errLog已在包内初始化,并且是私有的。 打印到可能会或可能不会出现的标准错误; 也就是说,进程可能出于其他原因选择关闭描述符。 但是,即使不是这样,用户对于日志记录也可能有不同的想法(考虑文件,syslog等)。 该驱动程序可以提供此默认记录器,但也可以允许用户设置其他记录器。

一旦有空余时间,我将为前面提到的问题准备一个小例子,并写一份报告。

谢谢!

@gkristic关于记录器-您的意思是类似https://github.com/go-sql-driver/mysql/pull/182 (一周前合并为master)?

@arnehormann哦,伙计...就是那个。 我一直在使用v1.1。 我在发布之前也检查了master上的其他内容,但忘了检查日志记录。 对不起,谢谢!

@gkristic根本不是问题:咧嘴笑:

在下一个版本之前应该做的任何更改? 欢迎PRs :)

大家好,这里是go-sql-driver的新用户。 我注意到类似的问题,但想知道是否有人可以帮助我确认原因是否相同? 在使用goroutine的长期运行的cron中,我通常会收到以下内容。

[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

我非常愿意在这里弄脏我的手,只是在寻找有关如何解决该问题的指导。 在某些情况下可以忽略此“无效连接”错误吗? 如果检测到此连接,是否可以自动获取另一个连接?

呃,哦...现在我知道了,我错过了上周五的@julienschmidt发表的评论。 (我向朱利安道歉。) @rmulley ,您似乎遇到了我在上面描述的相同问题。 看这个评论。 statement.go:24上的“无效连接”是无害的。 驱动程序应该通过选择其他连接来做适当的事情。 不过,我不确定“忙缓冲区”; 我不记得曾经看到过。 自从我检查了这段代码已经有一段时间了。 我将抽出一些时间再看一遍,看看是否能帮上忙。 不幸的是,这不可能在下周结束之前发生。 但是到那时我会再给你的。

@rmulley :对我来说,这似乎与这个问题无关。
如果您使用的是go get安装的版本(这是旧版本),请尝试使用当前的git master版本重现此错误。
请再打开一期新书。 触发此错误的最小代码示例肯定会有所帮助。

似乎(b *buffer) takeBuffer返回nil 。 这似乎仅在b.length > 0 。 这意味着由于某种原因,缓冲区中有未读的数据。
我以前从未见过此错误,并且仅实施了这些额外的检查以提高安全性。 我永远不会相信这种错误。

根据#206,此错误实际上在从尖端运行go时消失了。 实际上不是这样吗?

首先,对我在度假中的迟到答复感到抱歉,然后忘记跟进。 我确保我拥有最新版本的MySQL驱动程序,并且现在正在使用Go 1.3进行测试。 看来我现在在错误消息中看到了更多详细信息。

[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

这是我的MySQL问题吗? (关于如何解决此问题,我没有在网上找到任何有用的信息)
还是我可以检查一下然后以某种方式重新连接我的代码的东西?

我遇到了与rmulley描述的问题相同的问题。 不同的是,“忙缓冲区”出现在极短的查询中(短至1 Query + 2 Exec)。

我觉得问题与准备好的陈述有关。 我发现如果我在交易中准备了一份声明,例如

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

在准备另一条语句之前,我必须关闭此stmt,否则每次都会遇到“忙缓冲区”。 如果我不使用准备好的语句,例如直接对tx进行操作,例如

 tx.Query("...")

或者

tx.Exec("...")

,很好。

并且,如果我准备一条语句然后执行其他Query或Exec其他内容,那也很好...只是在不关闭前一条语句的情况下不要准备另一条语句,而且看起来还不错。

希望这确实是问题所在。

谢谢。

您可以创建一个小型Go程序来重现错误吗?
它似乎绝对是驱动程序中的错误,但与此处报告的原始问题无关。
请创建一个新的问题。

我认为这是问题所在:

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

我刚遇到类似的繁忙缓冲区问题,可以确认@arnehormann似乎是正确的。 当行对象仍处于打开状态时,尝试对多个查询使用同一事务时,会发生此问题

嗨,大家好,我不知道这个问题是否得到解决。 我在用“ Exec”执行的短插入中看到此问题->

var sql =“插入表(f1,f2 ... f25)值(?,?,...?)中
_,err:= db.Exec(sql,...)

大约4000次后,有时有5000次插入,我得到“意外的EOF”和“繁忙的缓冲区”。
插入是紧密的(在for循环中),但是每个插入之间都有一个REST请求,因此,触发的速度不是那么快。 相同的连接参考。 这是Go 1.3。

谢谢,
萨尔

@Sal-使用go 1.4会发生什么?

在2014年12月31日,星期三,晚上10:11,Sal A. Magnone [email protected]
写道:

嗨,大家好,我不知道这个问题是否得到解决。 我看到了
用“ Exec”执行短插入的问题->

var sql =“插入表(f1,f2 ... f25)值(?,?,...?)中
_,err:= db.Exec(sql,...)

大约4000次之后,有时插入5000次,我得到“意外的EOF”和“忙碌”
缓冲”。
插入紧密(在for循环中),但是之间存在REST请求
每一个都没有那么快的开火; 相同的连接参考。 这是Go 1.3。

谢谢,
萨尔

-
直接回复此电子邮件或在GitHub上查看
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413。

感谢您的回复。

1.4 –相同的错误。 在大约20分钟内在4205个插件上死亡(每个插件之间都有网和屏幕I / O)。

我已经对代码进行了重构,可以选择从上次停止的地方开始。 因此,对于此应用程序而言并不重要,但如果这是一个累积请求问题,则对于该项目中的其他应用程序可能至关重要。

萨尔

来自:carbocation [mailto:[email protected]]
发送时间:2015年1月4日,星期日,上午9:50
至:go-sql-driver / mysql
抄送:Sal A. Magnone
主题:Re:[mysql]终止连接时出现奇怪的错误(#185)

@Sal-使用go 1.4会发生什么?

在2014年12月31日星期三晚上10:11,Sal A.Magnone < [email protected] [email protected] >
写道:

嗨,大家好,我不知道这个问题是否得到解决。 我看到了
用“ Exec”执行短插入的问题->

var sql =“插入表(f1,f2 ... f25)值(?,?,...?)中
_,err:= db.Exec(sql,...)

大约4000次之后,有时插入5000次,我得到“意外的EOF”和“忙碌”
缓冲”。
插入紧密(在for循环中),但是之间存在REST请求
每一个都没有那么快的开火; 相同的连接参考。 这是Go 1.3。

谢谢,
萨尔

-
直接回复此电子邮件或在GitHub上查看
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413。

-
直接回复此电子邮件,或在GitHub https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68635254上查看。 https://github.com/notifications/beacon/AA4DdvfCFMdiqPlTZITEs9VrxyyJqqFQks5neUqigaJpZM4BSM1b.gif

这个线程现在变成几个线程了吗? 是否应该将最新评论放到新的期刊中,并且此评论已经结束?

@xaprb我同意,我认为现在有一些https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413引入新版本。

此页面是否有帮助?
0 / 5 - 0 等级