英文:
Do we need to close DB connection before closing application in Go?
问题
在Go语言中,当使用SQL数据库时,在关闭应用程序之前是否需要关闭数据库(db.Close
)?数据库会自动检测到连接已断开吗?
英文:
In Go, when using a SQL database, does one need to close the DB (db.Close
) before closing an application? Will the DB automatically detect that the connection has died?
答案1
得分: 4
DB将尽力检测,但如果没有成功,可能无法检测到。最好尽快释放已获取的内容。
send()
系统调用将等待TCP连接发送数据,但客户端不会接收任何内容。
-
发生了断电、网络问题或未正确释放资源的裸退出。TCP keepalive机制将启动并尝试检测连接是否已断开。
-
客户端暂停并且不接收任何数据,在这种情况下,
send()
将阻塞。
因此,可能会阻止:
- 集群的优雅关闭。
- 如果作为事务的一部分持有独占锁,例如PostgreSQL中的
自动清理
,则会阻止事件地平线的推进。
服务器keepalive配置可以缩短以更早地检测到它(例如,默认的PostgreSQL配置中的~2h 12m
对于工作负载来说可能太长)。
可能存在最大打开连接数的硬限制,在检测之前,一些连接将成为僵尸连接(不可用但会减少限制)。
英文:
DB will do its best to detect but with no luck, it may not be able to detect. Better to release what is acquired as soon as possible.
send()
system call will wait for TCP connection to send data but client won't receive anything.
-
Power failure, network issue or bare exit happened without properly releasing resources. TCP keepalive mechanism will kick in and try to detect that connection is dead.
-
Client is paused and doesn't receive any data, in this case
send()
will block.
As a result, it may prevent
- Graceful shutdown of cluster.
- Advancing event horizon if it was holding exclusive locks as a part of transaction such as
auto vacuum
in postgresql.
Server keepalive config could be shortened to detect it earlier. (For example, ~2h 12m
default in postgresql will be very long according to workload).
There may be a hard limit on max open connections, until detection, some connections will be zombie (there, unusable but decreases limit).
答案2
得分: 3
数据库将会注意到连接已经断开,并采取适当的措施:例如,所有在该连接上活动的未提交的事务将被回滚,并且用户会话将被终止。
但请注意,从数据库引擎的角度来看,这是一个“恢复”场景:它不能在客户端断开连接时直接抛出异常;相反,它必须采取明确的操作以保持一致的状态。
另一方面,当程序以“正常方式”关闭(即不是由于恐慌或log.Fatal()
引起)时,关闭属性并不是那么困难。而且由于sql.DB
实例通常是程序范围内的全局变量,所以更简单:只需像Matt建议的那样在main()
中尝试关闭它。
英文:
The database will notice the connection had died and take appropriate actions: for instance, all uncommitted transactions active on that connection will be rolled back and the user session will be terminated.
But notice that this is a "recovery" scenario from the point of view of the database engine: it cannot just throw up when a client disconnects; it rather have to take explicit actions to have consistent state.
On the other hand, to shut down property when the program goes down "the normal way" (that is, not because of a panic or log.Fatal()
) is really not that hard. And since the sql.DB
instance is usually a program-wide global variable, its even simpler: just try closing it in main()
like Matt suggested.
答案3
得分: 1
如果你在任何函数中初始化连接,通常最好将关闭调用延迟到立即关闭,即:
conn := sql.Connect() // 例如
defer conn.Close()
这将在封闭函数退出时关闭连接。
当在main
函数中使用时,这非常方便,因为一旦程序退出,将会调用Close()
。
英文:
If you're initialising a connection in any function, you're normally better off deferring the call to close immediately, i.e.
conn := sql.Connect() // for example
defer conn.Close()
Which will close the connection once the enclosing function exits.
This is handy when used in a main
function since once the program exits, the call to Close()
will happen.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论