You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:54:21