Mysql: 太多联系

创建于 2013-07-23  ·  9评论  ·  资料来源: go-sql-driver/mysql

调用db.sqlDB.Query()时,看到错误消息“ Too man connections”。 在深入探讨此问题之前,我想知道是否存在已知问题。

有什么想法吗?

013/07/23 03:05:35 yy.UpdateThingy()db.go:264 [无法将记录插入XXXX:错误1040:连接过多]

我正在使用1.1.1版的go:
go版本go1.1.1 linux / 386

我正在使用mysql驱动程序版本:
v1.0.1

MySql版本:
服务器版本:5.5.22-0ubuntu1(Ubuntu)

这是我的一个查询的示例:
行,错误=
db.sqlDB.Query(“插入XXXX(yyyy)值(?)”,
连接.ZZZZ)
如果err!= nil {
_ = rows.Close();
返回结果,错误
}
_ = rows.Close();

我添加了“ rows.Close()”,希望它可以解决此问题,但不会造成麻烦。

仅供参考,我的某些查询使用“ rows.Scan”,有些则没有。

question working as intended

最有用的评论

选项1:并发度太高

您有太多并发数据库访问。 在这种情况下,您必须手动限制并发连接的数量,直到数据库/ sql软件包在将来的版本中提供阻塞机制为止。 但是在许多情况下,缓存/异步更新将是更好的选择。

选项2:连接泄漏

您的程序很可能只是在泄漏数据库连接。 如果您没有关闭db.Query返回的rows db.Query或忘记了结束事务(在数据库/ sql的tx api中),则会发生这种情况。

我的一般建议是使用

  • db.Exec如果您不希望返回行)(换句话说,您不会Scan任何东西)。 执行后,连接立即免费。
  • db.QueryRow如果您希望一行)。 如果使用链式语法,则无法泄漏连接
  • db.Query如果您希望有多行)。 通过读取所有返回的行(循环rows.Next )或调用rows.Close “释放”连接非常重要。 可以肯定的是,推迟rows.Close通话是个好主意。 不要忘记错误情况等。

所有9条评论

请在这里看看: https :

不要使用.Query,而要使用.Exec。

选项1:并发度太高

您有太多并发数据库访问。 在这种情况下,您必须手动限制并发连接的数量,直到数据库/ sql软件包在将来的版本中提供阻塞机制为止。 但是在许多情况下,缓存/异步更新将是更好的选择。

选项2:连接泄漏

您的程序很可能只是在泄漏数据库连接。 如果您没有关闭db.Query返回的rows db.Query或忘记了结束事务(在数据库/ sql的tx api中),则会发生这种情况。

我的一般建议是使用

  • db.Exec如果您不希望返回行)(换句话说,您不会Scan任何东西)。 执行后,连接立即免费。
  • db.QueryRow如果您希望一行)。 如果使用链式语法,则无法泄漏连接
  • db.Query如果您希望有多行)。 通过读取所有返回的行(循环rows.Next )或调用rows.Close “释放”连接非常重要。 可以肯定的是,推迟rows.Close通话是个好主意。 不要忘记错误情况等。

我将“ db.Query()”更改为“ db.Prepare()和db.Exec()”,从而解决了我的问题。 感谢您提供快速,出色的答案。

我也是。
并且,我使用“ db.Prepare()和db.Exec()”,

var db * sql.DB

func getdb()* sql.DB {
db,err = sql.Open(“ mysql”,connArgs)
db.SetMaxIdleConns(100)
返回数据库
}

func foo(db * sql.DB){
做点东西...
smint,err:= db.Prepare(....)
延迟smint.Close()
smint.Exec(....)
}

func main(){
转到func(){
db = get_db()
延迟db.Close()
foo(db)
}()
}

try go 1.3
----- 原始邮件 -----
发件人:liutaihua [email protected]
收件人:go-sql-driver/mysql [email protected]
主题:Re: [mysql] Too many connections (#111)
日期:2014年07月16日 15点43分

还有...为什么要在main中启动goroutine?
如果您的代码确实看起来像这样,则在goroutine运行之前main可能会(并且可能会)退出,并且您的程序将什么也不做。
只需删除go func(){}() 。 您会过得更好。

抱歉,我的描述实际上是以下代码:

func socke_server(){
为了 {
// accept_something_from_socket作为接收
go func(some_receive){
db = get_db()
延迟db.Close()
foo(db)
}
}
}

func main(){
socke_server()
}

但是,现在,我使用了Unix域协议(' user:pwd @ unix (/tmp/mysql.sock)/'),它已修复。

谢谢回复

您也不应该这样做-可能会起作用,但是速度很慢。

将accept-loop放入main。
将goroutine转换为顶级函数。
将您的get_db代码放在主数据库的顶部,并延迟db.Close到那里(并且仅在那附近)。
不要像这样打开和关闭数据库。

尝试以下代码:

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

谢谢,我明白了。

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