我粘贴了一个可复制性最低的测试代码.简言之,当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()完全遍历结果集;根据the docs:

关闭关闭行,防止进一步枚举.如果调用Next并返回false,并且没有其他结果集,则行将自动关闭,只需判断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)
   }
}

For this to be useful you need to iterate through the rows (see the 100).

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

请注意,因为您的查询没有参数(并且您只使用了stmt次),所以调用Prepare没有任何好处;以下内容更简单,结果相同:

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

Go相关问答推荐

Google OAuth2没有刷新令牌

如何使用Promela建模语言对Golang RWLock进行建模

按键值排序字符串- Golang

创建使用逗号而不是加号分隔OU的CSR

如何执行asn 1 marshal/unmarshal和omit字段?

一次打印用户输入的字符串n次

Go安装成功但没有输出简单的Hello World

如何在 Go 服务中导入 monorepo 中的包?

一个Go module可以和之前的非module模块发布在同一个路径下吗?

最长连续重复的字符golang

如何以干净的方式在中间件中注入 repo 或服务?

GoLang:net.LookupHost 返回重复的 ips

具有未导出字段的 struct 类型之间的转换

golang pic.ShowImage 为什么它不生成图像而是向我发送base64值

从 Makefile 运行时权限被拒绝

Golang 工作池实现意外工作

在 Raspberry Pi4 上下载 Go Mod

递归数据 struct 解组在 Go Lang Protobuf 中给出错误无法解析无效的线格式数据

如何从 docker-compose 命令运行 2 个不同的命令:

go routine 和接收错误或成功的通道