Golang中connectionOpener goroutine运行1500分钟问题探讨
Golang中connectionOpener goroutine运行1500分钟问题探讨 大家好,
我们在生产环境中遇到了一个内存分配/泄漏问题。添加了PProf后发现,自构建启动以来,有一个SQL goroutine一直处于唤醒状态。
我想知道,当goroutine运行超过1500-1800分钟时,这是否是一个严重问题?
以下是代码片段:
目录结构:
MAIN 文件.GO
Db.GO
Pprof:pprof显示一个名为connectionOpener的goroutine,其运行时间持续增加。
goroutine 19 [select, 1482 minutes]:
database/sql.(*DB).connectionOpener(0xc00049d110, {0xf83e10, 0xc000181a40}) /usr/local/go/src/database/sql/sql.go:1218 +0x8d
created by database/sql.OpenDB /usr/local/go/src/database/sql/sql.go:791 +0x18d
goroutine 26 [select, 1482 minutes]: database/sql.(*DB).connectionOpener(0xc00049c1a0, {0xf83e10, 0xc00011c0f0}) /usr/local/go/src/database/sql/sql.go:1218 +0x8d
created by database/sql.OpenDB /usr/local/go/src/database/sql/sql.go:791 +0x18d
is it normal to have this open for such a long time ?
from https://kumakichi.github.io/goroutine-leak.html seen that we need to close
the connection.but closing the connection
using the reference of db is correct ? I mean suspecting the overall structure.
Kindly help
更多关于Golang中connectionOpener goroutine运行1500分钟问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你设置了最大连接数吗?
更多关于Golang中connectionOpener goroutine运行1500分钟问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
您的数据库连接不应放在 goroutine 中。 如果您需要数据库连接,应在应用程序启动阶段设置它,我的意思是将其放入您的 main() 函数中。
这是正常的数据库连接池行为。connectionOpener goroutine 是 database/sql 包内部用于异步建立数据库连接的协程,它会一直运行直到数据库连接池关闭。
示例代码展示正确的连接关闭方式:
package main
import (
"database/sql"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
// 打开数据库连接
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
log.Fatal(err)
}
defer db.Close() // 确保程序退出时关闭连接池
// 配置连接池参数
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
// 使用数据库连接
rows, err := db.Query("SELECT * FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// 处理查询结果...
}
关键点:
connectionOpenergoroutine 会持续运行,这是设计使然- 使用
defer db.Close()确保程序退出时释放所有资源 - 通过
SetConnMaxLifetime设置连接最大生命周期,避免连接长时间闲置 - 每个查询后及时关闭
rows.Close()
如果怀疑内存泄漏,检查:
- 是否在所有代码路径上都正确调用了
db.Close() - 是否每个
Query/Exec后都调用了rows.Close()/stmt.Close() - 连接池参数配置是否合理
运行时间长的 connectionOpener 本身不是问题,但需要确保连接池被正确管理和最终释放。

