在Java中什么时候不应该使用数据库连接池?

12

我可以找到许多关于如何使用连接池以及为什么这是个好主意的问题,但我想知道我是否真的需要它。

我正在创建一个服务器应用程序,虽然它是多线程的,但我已经小心翼翼地确保只有一个线程能够访问我的数据库连接。

那么使用连接池有什么意义呢?

我不能只在生命周期的开始时打开一个连接并永久使用它吗,或者如果连接空闲太长时间会超时吗?

我绝对必须在使用完后调用close()来关闭连接吗,还是只需要在ResultSet和/或Statement上调用close()就足够了?


请查看以下链接:https://dev59.com/OGQo5IYBdhLWcg3wZelg。 - Amit Bhati
2
“关闭原因为主观性较强”,为什么?如果有研究提供了在不使用连接池时的实用示例,那就不是基于个人意见的判断。 - J. Doe
3个回答

9
什么是“数据库连接”?它是与您的数据库会话相关联的会话,因此:
  • 有客户端和服务器端的会话状态
  • 有一个与该会话相关联的事务
现在,由于您的客户端应用程序是多线程的,我怀疑只有极少数情况下您的设置才有意义,即:
  • 您不使用会话状态,甚至是无意中(这可能是供应商特定的)
  • 您不使用事务并始终自动提交
  • 即使进行了自动提交,仍可能存在竞争条件,因此您确保这些情况不会发生
  • 您非常确定每个语句只需要很少的时间,立即释放资源
在所有其他情况下,您希望每个客户端线程拥有一个连接,或者在反应性/异步环境中,您至少希望每个隔离的数据库交互具有一个连接。而且,由于创建新连接很昂贵(即初始化服务器端会话状态等),人们简单地使用连接池。实际上,连接池中可以只有一个连接(根据您的要求),并且它仍然是您使用的良好抽象。那么,为什么要编写自己的连接池?
关于您的具体问题:

那么使用连接池有什么意义吗?

除了非常简单的情况(见上文),通常最好使用连接池。

我不能在生命周期开始时打开连接并永久使用它,或者如果空闲时间太长就会超时吗?

当然可以。通常,在JDBC驱动程序或其他客户端库中有设置以防止这些超时或重新连接。
这种方法的完美用例是迁移脚本、批处理脚本、简单测试脚本、简单的Swing应用程序等等。所有这些都不需要连接池。

是否绝对必须在使用后调用close()关闭我的连接,或只需在ResultSet和/或Statement上调用close()即可?

应该在从DataSource.getConnection()获取的连接上调用close()(例如,当连接池实现DataSource时)。
如果您管理自己的生命周期,则不必在连接上调用close()。

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Mikkel Ravnholt Simonsen
@MikkelRavnholtSimonsen:一个会话/连接可以有多个串行事务,是的。无论您是自动提交还是使用多语句事务,都没有关系。实际上,当您使用连接池时,这正是发生的情况。客户端进程检出连接,使用它来运行一个(几个?)事务,并将其返回到池中,以便另一个客户端进程可以使用它。即使您只想要一个连接,这也是您需要的。那么为什么要自己实现连接池呢? - Lukas Eder
那么为什么要自己实现连接池呢? - 嗯,我想要避免完全实现一个连接池。我无法看到在实际上是单线程环境中使用连接池的论点(我知道我说服务器是多线程的,但有一个专用于与数据库通信的单个线程)。我倾向于只使用一个连接,因为我能找到的所有东西都说要使用连接池,但我并不认为这是不必要的开销。 - Mikkel Ravnholt Simonsen
我认为我说得很清楚了。有一些情况下不使用连接池是有意义的。虽然这种情况很少见,因为人们通常不想冒险使整个应用程序在与数据库交互的单个线程上被阻塞。但是如果你非常确定,那就去尝试吧。 - Lukas Eder
好的,感谢您抽出时间帮助我更好地理解这整个事情,也许我应该接受连接池并尝试重新思考我的设计,以便我可以利用它们所拥有的好处。 - Mikkel Ravnholt Simonsen
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Lukas Eder

2
数据库连接的创建成本很高,因此当您有大量请求需要处理且每个请求通常只需短时间时,连接池就发挥作用了。您可以在新的上下文中重复使用以前的数据库连接,以避免为每个请求设置新的数据库连接所需的成本。
避免使用数据库连接的主要原因是您的应用程序解决问题的方法不适合适应数据库连接池。对于池,使单个共享连接具有高性能的某些优化可能必须被撤消并重新验证才能正确地采用池并有效地使用池。
此外,虽然许多人担心连接的延迟,但池通过准备一组连接来减少延迟;您的数据库现在是多个连接的主机,这意味着您的应用程序的“休息”状态将使用更多资源。通常,在大多数环境中,这还不足以产生很大的差异。
池化连接有时可以实现更多查询和提交的重新排序,并且未编写防御性处理数据库状态随数据库更改而更改的代码可能需要进行额外的重新工作和验证。请记住,这不是连接池的弱点,而是数据库处理逻辑中潜在的错误(因为所有数据库都应该被视为共享资源,并且应该有这些类型的逻辑检查)。

0
我能不能在生命周期的开始时打开一个数据库连接并永久使用它,或者如果长时间不活动会超时呢?
连接有时会过期、断开、失败。
许多连接池能够自动检查连接状态,关闭过期/失败的连接,并在需要时重新打开新连接。
考虑一下网络瞬间中断或者有人重启数据库服务器的情况。
连接池会在故障后自动恢复与数据库的连接 - 你不必在此之后重新启动应用程序。
你可以在你的dao类中实现这样的功能...但是连接池已经有了这个功能,直接使用更容易。
如果你不想要更多的连接,你可以配置一个只有1个连接的池。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接