问大家一个比较初级的问题,在写 golang 的时候发现一个问题,公司的项目都没有做程序退出时的连接清理工作。
var DB *sql.DB
func init() {
var err error
DB, err = sql.Open("mysql", "root:root@tcp(127.0.0.1)/test")
if err != nil {
log.Fatal(err)
}
}
func main() {
}
基本就是初始化之后,就直接开始使用了,go 会在程序内部自动维护一个连接池,在程序退出的时候也没有手动Close()
这样不知道会不会有其他的问题。比如未正确关闭的连接会导致 mysql 内连接数暴涨,之类的问题。如果这样没有问题,那是不是 redis
monogodb
这些都可以不用手动关闭连接。
1
gamexg 2023-04-10 23:55:57 +08:00
操作系统会负责在进程结束时关闭进程打开的各个资源,包含 tcp 连接.
如果程序一直使用,直至程序结束时才要释放的连接,那么大部分情况下可以不手动关闭。 |
2
LeegoYih 2023-04-11 00:37:01 +08:00
进程都结束了,资源肯定都释放了,除非是操作系统的 bug
|
3
kwh 2023-04-11 00:46:11 +08:00
经你这么一问,我发现我从没思考过,程序停止运行后,连接 是否会断开的问题。
不过在我心里应该是默认断开的, |
4
FrankFang128 2023-04-11 06:12:10 +08:00
根据 go database/sql tutorial 的内容:
如果你希望 sql.DB 在当前函数结束之后关闭,那么 defer db.Close() 是一个好习惯 虽然在完成数据库操作后调用 Close() 方法是惯用法,但 sql.DB 是被设计成长时间使用的。不要频繁地 Open() 和 Close() 数据库,而是为需要访问的每个不同数据库创建一个 sql.DB 对象,并将其保留到程序完成访问该数据库为止。你应该保持 sql.DB 处于 Open 状态,然后把 sql.DB 传给需要访问数据的模块,或者你也可以让 sql.DB 全局可用。不要在一个局部函数中调用 Open() 和 Close() 方法。而是把 sql.DB 作为参数传递给它。 如果你不把 sql.DB 当作一个长时间使用的对象,那么你可能会遇到一些问题,比如连接的复用和共享效率低、网络资源被耗尽,或者由于大量的 TCP 连接停留在 TIME_WAIT 状态而出现间歇性故障。这些问题说明你没有按照 database/sql 库的设计来使用它。 以上内容不是 AI 生成的,是我自己翻译的。https://ffang.notion.site/Go-database-sql-tutorial-868217491c51448b8235699c349068c6 |
5
aababc OP @FrankFang128 这个说法是没有问题的,在程序运行的时候只会创建一次,但是问题是在程序退出的时候是否需要关闭,也没有给出明确的说法
|
6
FrankFang128 2023-04-11 17:50:11 +08:00
文中的建议是:不管程序退出关不关闭,你最好 defer close 一下
|