go 中的连接是否需要关闭

2023-04-10 23:22:46 +08:00
 aababc

问大家一个比较初级的问题,在写 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 这些都可以不用手动关闭连接。

1724 次点击
所在节点    问与答
6 条回复
gamexg
2023-04-10 23:55:57 +08:00
操作系统会负责在进程结束时关闭进程打开的各个资源,包含 tcp 连接.
如果程序一直使用,直至程序结束时才要释放的连接,那么大部分情况下可以不手动关闭。
LeegoYih
2023-04-11 00:37:01 +08:00
进程都结束了,资源肯定都释放了,除非是操作系统的 bug
kwh
2023-04-11 00:46:11 +08:00
经你这么一问,我发现我从没思考过,程序停止运行后,连接 是否会断开的问题。
不过在我心里应该是默认断开的,
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
aababc
2023-04-11 10:10:02 +08:00
@FrankFang128 这个说法是没有问题的,在程序运行的时候只会创建一次,但是问题是在程序退出的时候是否需要关闭,也没有给出明确的说法
FrankFang128
2023-04-11 17:50:11 +08:00
文中的建议是:不管程序退出关不关闭,你最好 defer close 一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/931382

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX