调用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”,有些则没有。
请在这里看看: https :
不要使用.Query,而要使用.Exec。
您有太多并发数据库访问。 在这种情况下,您必须手动限制并发连接的数量,直到数据库/ sql软件包在将来的版本中提供阻塞机制为止。 但是在许多情况下,缓存/异步更新将是更好的选择。
您的程序很可能只是在泄漏数据库连接。 如果您没有关闭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)
}
}
谢谢,我明白了。
最有用的评论
选项1:并发度太高
您有太多并发数据库访问。 在这种情况下,您必须手动限制并发连接的数量,直到数据库/ sql软件包在将来的版本中提供阻塞机制为止。 但是在许多情况下,缓存/异步更新将是更好的选择。
选项2:连接泄漏
您的程序很可能只是在泄漏数据库连接。 如果您没有关闭
db.Query
返回的rows
db.Query
或忘记了结束事务(在数据库/ sql的tx api中),则会发生这种情况。我的一般建议是使用
db.Exec
如果您不希望返回行)(换句话说,您不会Scan
任何东西)。 执行后,连接立即免费。db.QueryRow
如果您希望有一行)。 如果使用链式语法,则无法泄漏连接db.Query
如果您希望有多行)。 通过读取所有返回的行(循环rows.Next
)或调用rows.Close
“释放”连接非常重要。 可以肯定的是,推迟rows.Close
通话是个好主意。 不要忘记错误情况等。