在Go语言中,在关闭应用程序之前需要关闭数据库连接吗?

huangapple go评论82阅读模式
英文:

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连接发送数据,但客户端不会接收任何内容。

  1. 发生了断电、网络问题或未正确释放资源的裸退出。TCP keepalive机制将启动并尝试检测连接是否已断开。

  2. 客户端暂停并且不接收任何数据,在这种情况下,send()将阻塞。

因此,可能会阻止:

  1. 集群的优雅关闭。
  2. 如果作为事务的一部分持有独占锁,例如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.

  1. 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.

  2. Client is paused and doesn't receive any data, in this case send() will block.

As a result, it may prevent

  1. Graceful shutdown of cluster.
  2. 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.

huangapple
  • 本文由 发表于 2015年12月9日 17:36:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/34175299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定