在关闭Go中的应用程序之前是否需要关闭数据库连接?

时间:2021-03-04 14:08:17

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?

在Go中,当使用SQL数据库时,是否需要在关闭应用程序之前关闭数据库(db.Close)? DB会自动检测到连接已经死亡吗?

4 个解决方案

#1


3  

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.

DB会尽力检测,但没有运气,可能无法检测到。最好尽快发布所获得的内容。

send() system call will wait for TCP connection to send data but client won't receive anything.

send()系统调用将等待TCP连接发送数据,但客户端将不会收到任何内容。

  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.

    没有正确释放资源就会发生电源故障,网络问题或裸露退出。 TCP keepalive机制将启动并尝试检测该连接已死。

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

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

As a result, it may prevent

结果,它可能会阻止

  1. Graceful shutdown of cluster.
  2. 正常关闭集群。

  3. Advancing event horizon if it was holding exclusive locks as a part of transaction such as auto vacuum in postgresql.
  4. 如果它持有独占锁作为事务的一部分,如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).

可以缩短服务器keepalive配置以便更早地检测它。 (例如,根据工作量,postgresql中默认的~2h 12m将非常长)。

There may be a hard limit on max open connections, until detection, some connections will be zombie (there, unusable but decreases limit).

最大开放连接可能存在硬限制,直到检测到,某些连接将是僵尸(存在,不可用但减少限制)。

#2


1  

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.

另一方面,当程序按“正常方式”(即不是因为恐慌或log.Fatal())而关闭属性时实际上并不那么难。由于sql.DB实例通常是一个程序范围的全局变量,它更简单:只需尝试在main()中关闭它,就像Matt建议的那样。

#3


0  

It is good practice to release any resource which was utilized. What DB are you utilizing.

优先发布任何已使用的资源。你正在使用什么数据库。

#4


0  

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.

这在主函数中使用时很方便,因为一旦程序退出,就会发生对Close()的调用。

#1


3  

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.

DB会尽力检测,但没有运气,可能无法检测到。最好尽快发布所获得的内容。

send() system call will wait for TCP connection to send data but client won't receive anything.

send()系统调用将等待TCP连接发送数据,但客户端将不会收到任何内容。

  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.

    没有正确释放资源就会发生电源故障,网络问题或裸露退出。 TCP keepalive机制将启动并尝试检测该连接已死。

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

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

As a result, it may prevent

结果,它可能会阻止

  1. Graceful shutdown of cluster.
  2. 正常关闭集群。

  3. Advancing event horizon if it was holding exclusive locks as a part of transaction such as auto vacuum in postgresql.
  4. 如果它持有独占锁作为事务的一部分,如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).

可以缩短服务器keepalive配置以便更早地检测它。 (例如,根据工作量,postgresql中默认的~2h 12m将非常长)。

There may be a hard limit on max open connections, until detection, some connections will be zombie (there, unusable but decreases limit).

最大开放连接可能存在硬限制,直到检测到,某些连接将是僵尸(存在,不可用但减少限制)。

#2


1  

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.

另一方面,当程序按“正常方式”(即不是因为恐慌或log.Fatal())而关闭属性时实际上并不那么难。由于sql.DB实例通常是一个程序范围的全局变量,它更简单:只需尝试在main()中关闭它,就像Matt建议的那样。

#3


0  

It is good practice to release any resource which was utilized. What DB are you utilizing.

优先发布任何已使用的资源。你正在使用什么数据库。

#4


0  

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.

这在主函数中使用时很方便,因为一旦程序退出,就会发生对Close()的调用。