我有一个 golang 应用程序,它使用 MySQL 作为后端数据库。该应用程序使用
*sql.DB
打开一个 sql.Open
,然后调用 PingContext
https://pkg.go.dev/database/sql#DB.PingContext 以确保我们可以与其交谈。
这是建立连接的代码
func (se *Executor) connect(ctx context.Context) error {
if se.DB != nil {
// If DB handle exists, ping it to make sure it's still alive
return se.DB.PingContext(ctx)
}
// Create a DB handle
dsn := fmt.Sprintf(mysqlDNSFormat, se.User, se.Pass, mysqlSocketPath)
var err error
se.DB, err = sql.Open("mysql", dsn)
if err != nil {
fmt.Printf("Failed to connect to mysql %v", err)
return err
}
// Make sure we can ping the DB before returning
if err = se.DB.PingContext(ctx); err != nil {
fmt.Printf("Failed during ping to mysql %v", err)
return err
}
return nil
}
第一次调用此函数时,我们将设置
se.DB
,然后后续调用仅 ping 数据库以确保它在执行任何查询之前已启动并运行。如果数据库重新启动,则 ping 可能会开始失败。这种情况有必要打电话给db.Close()
吗? PingContext
的文档说
PingContext 验证与数据库的连接是否仍然存在,并在必要时建立连接。
这意味着一旦数据库再次备份,
PingContext
将开始成功。它没有说明是否必须关闭数据库并再次重新打开。 db.Open
上的文档还建议该函数应该只调用一次。
返回的数据库对于多个 goroutine 并发使用是安全的,并维护自己的空闲连接池。因此,Open 函数应该只调用一次。很少需要关闭数据库。
预计 SQL 驱动程序会处理失败的连接,例如 Go-MySQL-Driver 表示: “自动处理断开的连接。”
请注意,仅因为您可以 ping 数据库,并不能保证连接在下一个请求时仍然处于活动状态。
最好是只发送请求,当由于网络问题而失败时,使用 ping 直到数据库备份,以避免重复构建失败的请求。