Golang database/sql设置SetMaxOpenConns后程序挂起问题求助
问题
设置SetMaxOpenConns(10)后,程序执行第10次查询后永久挂起,注释掉该设置则运行正常。曾找到早年相关讨论线程,问题似乎已解决并完成测试。请问是操作有误还是需要提交新issue?
复现代码
package main import ( "database/sql" "log" "time" _ "github.com/lib/pq" ) func main(){ // 建立数据库连接 db, err := sql.Open("postgres", "host=0.0.0.0 port=5432 user=postgres password=password dbname=test sslmode=disable") if err != nil { log.Fatal(err) } db.SetMaxOpenConns(10) // 注释此行问题解决 db.SetMaxIdleConns(10) db.SetConnMaxLifetime(10 * time.Second) // 查询次数超过最大打开连接数,程序会永久挂起 for i:=0; i<12; i++ { rows, err := Query(db) if err != nil { log.Fatal(err) } log.Println(i) log.Println(rows) } } func Query(db *sql.DB) (*sql.Rows, error){ stmt, err := db.Prepare("SELECT * FROM test;") if err != nil { log.Fatal(err) } defer stmt.Close() rows, err := stmt.Query() if err != nil { log.Fatal(err) } return rows, nil }
解答
- 问题根源:未关闭
*sql.Rows对象。每次查询返回的rows持有底层数据库连接,你在主循环中没有调用rows.Close(),导致连接一直被占用无法回收到连接池。当循环到第10次时,10个最大打开连接全部被占用,第11次请求会无限等待可用连接,最终挂起。 - 修复方式:在主循环中添加
defer rows.Close()释放连接:
for i:=0; i<12; i++ { rows, err := Query(db) if err != nil { log.Fatal(err) } defer rows.Close() // 释放连接回池 log.Println(i) log.Println(rows) }
- 补充说明:
stmt.Close()仅关闭预编译语句,不会释放stmt.Query()返回的rows持有的连接,必须显式关闭rows才能让连接回到池中复用。
内容的提问来源于stack exchange,提问作者maininformer
相关产品推荐
相关产品推荐

