Golang中MySQL连接在空闲约6分钟后自动关闭的问题探讨

Golang中MySQL连接在空闲约6分钟后自动关闭的问题探讨 以下是我的操作步骤:

  1. 在另一个包的 init() 函数中打开数据库连接(比如 “package model”,而不是 “package main”)
var conn *sql.DB

func init() {
	// connect to database
	dsn := os.Getenv("DB_USERNAME")+":" + os.Getenv("DB_PASSWORD") + "@tcp("+os.Getenv("DB_HOST")+")/"+os.Getenv("DB_DATABASE")
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatal("fail to connect to mysql")
	}
	conn = db
}
  1. 当需要查询数据库时,我会调用名为 InitSlave() 的方法,该方法会执行 conn.Ping()
func (m *Model) InitSlave() {
	err := conn.Ping()
	log.Println("Ping connection successful...")
	if err != nil {
		log.Fatal(err)
	}
	m.Slave = conn
}
  1. 运行应用程序,监听 8080 端口,此时访问网站正常

  2. 如果让应用程序空闲运行 6 到 7 分钟,再次尝试访问,会收到以下消息

operation timeout...

换句话说,无法再次加载网页…

如果我将 conn 声明为全局变量,我认为它会一直存在于内存中。所以每当我访问网站时,它都会向数据库发起查询,然后调用 conn.Ping(),会建立新连接或重用旧连接。我无法理解为什么在空闲几分钟后页面就无法加载了…

感谢帮助!微笑表情


更多关于Golang中MySQL连接在空闲约6分钟后自动关闭的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

确实需要看到更多代码才能充分评估这里的情况,例如我们无法看到您的服务函数,因此不知道您的模型类型是如何实例化的,可能还存在其他相关问题。

能否展示更多代码?

更多关于Golang中MySQL连接在空闲约6分钟后自动关闭的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我猜你的问题来自于使用了conn变量的副本。不要这样做,在你的程序中的每个查询都使用相同的conn变量。

我注意到的问题是,你在模型包中定义了一个通用模型类型下的连接池,但这个对象在创建实例之前实际上并不存在,而且如果它在函数作用域内创建,会被垃圾回收机制处理。

当我处理这种情况时,我会创建一个包装器,将连接指针从主包作为中间件传递给我的处理程序。

这是源代码

我想知道是否应该在每个请求中都调用 sql.Open(),比如在 func main() 中,而不仅仅是在 package modelinit() 函数中,不太确定,谢谢:)

func main() {
    fmt.Println("hello world")
}

不,sql.Open() 应该在 func init() 中只调用一次,以下是文档说明:

// 返回的 DB 可安全地被多个 goroutine 并发使用 // 并维护自己的空闲连接池。因此,Open // 函数应该只调用一次。很少需要 // 关闭 DB。

包装器解决方案看起来不错,我考虑使用它,谢谢 🙂

我发现了这个问题,情况相同。

我通过将最大连接生存时间设置为1分钟来解决这个问题,如下所示:

conn.SetConnMaxLifetime(time.Duration(1) * time.Minute)

这样任何连接都会在1分钟后被移除,而不会对连接池产生重大影响。

conn 是一个 *sql.DB 指针,文档说明:

DB 是一个数据库句柄,代表零个或多个底层连接的连接池。它可以安全地被多个 goroutine 并发使用。

因此 conn 应该始终是指向连接池的指针,并且可以安全地并发使用。
conn 的副本指向相同的内存地址,代表同一个连接池,所以像这样使用应该是安全的,对吗?
谢谢!微笑

回到顶部