问大家一个比较初级的问题,在写 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 rankFang128 2023-04-11 17:50:11 +08:00 文中的建议是:不管程序退出关不关闭,你最好 defer close 一下 |