【问题标题】:How to manage db connections on server?如何管理服务器上的数据库连接?
【发布时间】:2011-02-28 02:17:04
【问题描述】:

我的 Web 应用程序中的数据库连接存在严重问题。由于我从单例数据库类中为整个应用程序使用单个数据库连接,因此如果我尝试并发数据库操作(两个用户),数据库会回滚事务。 这是我使用的静态方法:

所有线程/servlet 调用静态 Database.doSomething(...) 方法,这些方法又调用下面的方法。

private static /* synchronized*/ Connection getConnection(final boolean autoCommit) throws SQLException {
    if (con == null) {
        con = new MyRegistrationBean().getConnection();
    }
    con.setAutoCommit(true); //TODO
    return con;
}

推荐的管理这个数据库连接的方法是什么,这样我就不会遇到同样的问题。

【问题讨论】:

  • 检查数据库查询日志,或者开始制作自己的日志,看看出了什么问题。由于两个并发用户,没有数据库永远不会回滚,您的查询可能有错误或丢失提交。

标签: multithreading postgresql servlets jdbc


【解决方案1】:

Connection 永远打开是一个非常糟糕的主意。它没有无限的生命周期,每当数据库超时连接并关闭它时,您的应用程序可能会崩溃。最佳做法是在最短可能的范围内获取关闭ConnectionStatementResultSet,以避免资源泄漏和泄漏导致的潜在应用程序崩溃和超时。

由于连接数据库是一项昂贵的任务,您应该考虑使用连接池来提高连接性能。一个体面的应用服务器/servlet 容器通常已经提供了类似于 JNDI DataSource 的连接池特性。有关如何创建它的详细信息,请参阅其文档。例如 Tomcat,您可以找到它here

即使使用连接池,您仍然需要编写正确的 JDBC 代码:获取在尽可能短的范围内关闭所有资源。连接池将轮流担心实际关闭连接或只是将其释放回池以供进一步重用。

您可能会从 this article 如何以正确的方式完成 JDBC 基础知识获得更多见解。作为一个完全不同的选择,学习 EJB 和 JPA。它将为您抽象出所有 JDBC 样板文件到 oneliners 中。

希望这会有所帮助。

另见:

【讨论】:

  • 为了简单起见(现在),我可以接受打开和关闭连接所需的时间。实际上,我什至(还)不担心数据库超时后的崩溃。我的问题是关于同步连接到数据库的多个请求。我上面的方法不做任何同步。我不确定发生了什么,但似乎两个线程共享相同的连接,并且这本身就被检测为问题,或者第二个线程从第一个线程开始对其进行加固,再次被检测为错误。
  • 顺便说一句,我已经在每个 db 方法结束时关闭了连接,但这与这个单例连接冲突,因为一个线程可以在另一个线程完成之前关闭它。
  • 在尽可能短的范围内打开和关闭连接(在同一个方法块中)应该已经解决了连接被共享的问题。
  • 怎么样?! “我已经在每个 db 方法结束时关闭了连接,但这与这个单例连接冲突,因为一个线程可以在另一个线程完成之前关闭它。”您是否考虑我的数据库只有静态方法,因此线程 A 可能在方法 m(带有连接)中,而线程 B 也来并调用方法 m! (或 m',如果你愿意),当第二个 m 请求连接时,我遇到了问题。
  • 不,通过DriverManager#getConnection()DataSource#getConnection() 打开连接,而不是SomeBadSingleTon#getConnection()。按照文章链接仔细阅读。
【解决方案2】:

Singleton 应该是 JNDI 池连接本身;具有 getConnection()、查询方法等的数据库类不应是单例的,但如果您愿意,可以是静态的。

这样池子是无限存在的,可供所有用户使用,而查询块使用dataSource.getConnection()从池子中拉取连接;执行查询,然后关闭语句、结果集和连接(将其返回到池中)。

此外,JNDI 查找非常昂贵,因此在这种情况下使用单例是有意义的。

【讨论】:

    【解决方案3】:

    我没有太多使用 PostgreSql 的经验,但我从事过的所有 Web 应用程序都对页面上的每组操作使用一个连接,关闭它并在完成后处理它。

    这允许服务器汇集连接并阻止您遇到的问题。

    【讨论】:

    • 是的,但是不是为每个客户端请求创建一个新的 servlet 线程吗?然后,如果我每个 servlet 都有一个连接(在它的末尾关闭),我很快就会收到一个:致命错误:已经有太多连接。不是吗?
    猜你喜欢
    • 2016-12-17
    • 2014-03-17
    • 2015-11-22
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多