【问题标题】:How many JDBC connections in Java?Java中有多少个JDBC连接?
【发布时间】:2010-10-03 01:45:07
【问题描述】:

我有一个由大约 15 个方法组成的 Java 程序。而且,这些方法在程序执行过程中被非常频繁地调用。目前,我正在每个方法中创建一个新连接并在它们上调用语句(数据库设置在网络上的另一台机器上)。

我想知道的是:我是否应该在主方法中只创建一个连接并将其作为参数传递给所有需要连接对象的方法,因为它会显着减少程序中连接对象的数量,而不是在每种方法中都非常频繁地创建和关闭连接。

我怀疑我目前的设计并没有非常有效地使用资源,并且考虑到该程序将来可能会增长很多,还有很多改进的余地。

【问题讨论】:

    标签: java performance jdbc database-connection


    【解决方案1】:

    是的,您应该考虑重新使用连接,而不是每次都创建一个新连接。通常的程序是:

    • 猜测您的数据库可以合理处理多少个同时连接(例如,从数据库计算机上的每个 CPU 2 或 3 个开始,直到您发现这太少或太多 - 这往往取决于关于您的查询是如何受磁盘限制的)
    • 为这么多连接创建一个:本质上是一个类,您可以在每个方法开始时要求“下一个空闲连接”,然后在最后“传回”到池中每种方法的
    • 如果有可用连接,您的 getFreeConnection() 方法需要返回一个空闲连接,否则 (1) 创建一个新连接,直到您决定允许的最大连接数,或者 (2) 如果最大已创建,请等待其中一个免费
    • 我建议使用 Semaphore 类来管理连接;实际上,我在managing a resource pool with a Semaphore 的网站上有一篇简短的文章,其中包含一个我认为您可以适应您的目的的示例

    几个实际考虑:

    • 为了获得最佳性能,您需要小心不要在实际不使用连接来运行查询时“占用”连接。如果您从池中获取一次连接,然后将其传递给各种方法,则需要确保您不会意外地这样做。
    • 不要忘记将连接返回到池中! (试试/终于是你的朋友了……)
    • 在许多系统上,您无法“永远”保持连接打开:操作系统将在某个最长时间后关闭它们。因此,在您的“将连接返回到池”方法中,您需要考虑“退出”已经存在很长时间的连接(建立一些记忆机制,例如通过一个围绕实际 JDBC Connection 对象的包装器对象,您可以使用它来存储诸如此类的指标)
    • 您可能需要考虑使用准备好的语句。
    • 随着时间的推移,您可能需要调整连接池大小

    【讨论】:

    • 您能否详细说明一下准备好的语句如何提供帮助?
    • @neilCoffey 如果不考虑“退出”连接;为什么我们需要多个连接?一个单一的连接可以在任何地方使用;因为语句对象总是不同的?当我们需要应用程序中的多个连接时?
    • 如您所说,一个连接可用于运行(理论上)无限数量的查询。但它一次只能运行一个查询。在中等复杂的系统上,您通常需要考虑同时运行多个查询的可能性。
    【解决方案2】:

    您可以传递连接,或者更好地使用 Jakarta Database Connection Pooling 之类的东西。 http://commons.apache.org/dbcp/

    【讨论】:

      【解决方案3】:

      您应该为此使用连接池。

      这样你就可以请求连接并在完成后释放它并将其返回到池中

      如果另一个线程想要一个新连接并且该连接正在使用中,则可以创建一个新连接。如果没有其他线程正在使用连接,则可以重复使用该连接。

      这样,您可以以某种方式让您的应用保持原样(而不是到处传递连接),并且仍然可以正确使用资源。

      不幸的是,一流的 ConnectionPools 在独立应用程序中不是很容易使用(它们是应用程序服务器中的默认设置),可能一个微容器(例如 Sping)或一个好的框架(例如 Hibernate)可以让您使用。

      不过,从头开始编写代码并不难。

      :)

      This google search 将帮助您找到更多关于如何使用的信息。

      浏览

      【讨论】:

      • 如果不考虑“退出”连接;为什么我们需要多个连接?一个单一的连接可以在任何地方使用;因为语句对象总是不同的?当我们需要应用程序中的多个连接时?
      【解决方案4】:

      许多 JDBC 驱动程序会为您执行连接池,因此在这种情况下进行额外的池化几乎没有优势。我建议您查看 JDBC 驱动程序的文档。

      连接池的另一种方法是

      • 对于所有数据库访问具有同步访问的一个连接。这不允许并发,但非常简单。
      • 将连接存储在 ThreadLocal 变量中(覆盖 initialValue())如果有少量固定数量的线程,这很有效。

      否则,我建议使用连接池。

      【讨论】:

        【解决方案5】:

        如果您的应用程序是单线程的,或者它的所有数据库操作都从一个线程执行,则可以使用单个连接。假设您出于任何其他原因不需要多个连接,这将是迄今为止最简单的实现。

        根据您的驱动程序,在线程之间共享连接也可能是可行的 - 如果您相信您的驱动程序不会对其线程安全性撒谎,这也可以。有关详细信息,请参阅您的驱动程序文档。

        通常情况下,“连接”下面的对象不能安全地从多个线程中使用,因此通常不建议在线程之间共享 ResultSet、Statement 对象等 - 到目前为止,最好的策略是在创建它们的同一线程中使用它们;这通常很容易,因为这些对象通常不会保存太久。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-12
          • 2011-10-10
          • 1970-01-01
          • 2014-08-06
          • 2017-10-05
          • 1970-01-01
          相关资源
          最近更新 更多