Golang数据库/sql与SetMaxOpenConns挂起



我粘贴了一个可重复性最低的测试代码。简而言之,当SetMaxOpenConns设置为10时,程序将在10之后永远挂起。我在很久以前就发现了这个相关的线程,但它似乎得到了解决和测试:https://github.com/golang/go/issues/6593

请注意,通过注释掉SetMaxOpenConns,代码可以正常运行。

我做错了什么?还是我应该开一期新的?

1 package main
2
3 import (
4     "database/sql"
5     "log"
6     "time"
7     _ "github.com/lib/pq"
8 )
9
10 func main(){
11     // Establish db connection
12     db, err := sql.Open("postgres", "host=0.0.0.0 port=5432 user=postgres password=password dbname=test sslmode=disable")
13     if err != nil {
14         log.Fatal(err)
15     }
16
17     db.SetMaxOpenConns(10) // commenting this line will resolve the problem
18     db.SetMaxIdleConns(10)
19     db.SetConnMaxLifetime(10 * time.Second)
20
21     // Query more than max open; note that hangs forever
22     for i:=0; i<12; i++ {
23     rows, err := Query(db)
24     if err != nil {
25         log.Fatal(err)
26     }
27     log.Println(i)
28     log.Println(rows)
29     }
30 }
31
32 func Query(db *sql.DB) (*sql.Rows, error){
33     stmt, err := db.Prepare("SELECT * FROM test;")
34     if err != nil {
35         log.Fatal(err)
36     }
37
38     defer stmt.Close()
39
40     rows, err := stmt.Query()
41     if err != nil {
42         log.Fatal(err)
43     }
44
45     return rows, nil
46 }

您需要使用rows.Next完全迭代结果集和/或调用rows.Close();根据文件:

Close关闭行,阻止进一步枚举。如果Next被调用并返回false,并且没有其他结果集,那么Rows将自动关闭,只需检查Err的结果即可。Close是幂等的,不影响Err的结果。

类似于:

for i:=0; i<12; i++ {
rows, err := Query(db)
if err != nil {
log.Fatal(err)
}
log.Println(i)
log.Println(rows)
if err = rows.Close(); err != nil {
panic(err)
}
}

要使其有用,您需要遍历行(请参阅文档中的示例(

到数据库的连接将一直使用,直到结果集关闭(此时它将返回到池(。因为您是在循环中执行此操作的,所以最终会得到10个活动结果集,当您再次调用Query()时,sql包将等待连接可用(这永远不会发生(。

请注意,因为您的查询没有参数(并且您只使用过一次stmt(,所以调用Prepare没有任何好处;下面的比较简单,并且会有相同的结果:

func Query(db *sql.DB) (*sql.Rows, error) {
return db.Query("SELECT * FROM test;")
}

最新更新