Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tomcat web应用程序中Java和MySQL的连接池_Java_Mysql_Tomcat_Connection_Pooling - Fatal编程技术网

Tomcat web应用程序中Java和MySQL的连接池

Tomcat web应用程序中Java和MySQL的连接池,java,mysql,tomcat,connection,pooling,Java,Mysql,Tomcat,Connection,Pooling,我最近编写了一个Java web应用程序并将其部署到服务器上,我发现了一个在开发或测试期间没有出现的异常问题 当用户在这么长时间后登录并显示数据库中的数据时,该页面表示没有可查看的记录。但在页面刷新时,将根据分页规则显示前x条记录 查看日志,我发现: ERROR|19 09 2009|09 28 54|http-8080-4|myDataSharer.database_access.Database_Metadata_DBA| - Error getting types of columns o

我最近编写了一个Java web应用程序并将其部署到服务器上,我发现了一个在开发或测试期间没有出现的异常问题

当用户在这么长时间后登录并显示数据库中的数据时,该页面表示没有可查看的记录。但在页面刷新时,将根据分页规则显示前x条记录

查看日志,我发现:

ERROR|19 09 2009|09 28 54|http-8080-4|myDataSharer.database_access.Database_Metadata_DBA| - Error getting types of columns of tabular Dataset 12

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 

** BEGIN NESTED EXCEPTION ** 

java.io.EOFException

STACKTRACE:

java.io.EOFException
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1956)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2368)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2867)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1616)
等几百行

该应用程序目前可供大约100名用户使用,但尚未完全投入使用。它使用Apache Tomcat servlet/JSP和MySQL数据库之间的连接池,下面的代码示例构成了数据库操作的总体安排,每个页面通常有几个数据库操作:

// Gets a Dataset.
public static Dataset getDataset(int DatasetNo) {
    ConnectionPool_DBA pool = ConnectionPool_DBA.getInstance();
    Connection connection = pool.getConnection();
    PreparedStatement ps = null;
    ResultSet rs = null;

    String query = ("SELECT * " +
                    "FROM Dataset " +
                    "WHERE DatasetNo = ?;");

    try {
        ps = connection.prepareStatement(query);
        ps.setInt(1, DatasetNo);
        rs = ps.executeQuery();
        if (rs.next()) {
            Dataset d = new Dataset();
            d.setDatasetNo(rs.getInt("DatasetNo"));
            d.setDatasetName(rs.getString("DatasetName"));
            ...

            }

            return d;
        }
        else {
            return null;
        }
    }
    catch(Exception ex) {
        logger.error("Error getting Dataset " + DatasetNo + "\n", ex);            
        return null;
    }
    finally {
        DatabaseUtils.closeResultSet(rs);
        DatabaseUtils.closePreparedStatement(ps);
        pool.freeConnection(connection);
    }
}
有人能提出纠正这个问题的方法吗

我相信这是因为MySQL让连接投票连接打开了八个小时,但我不确定

谢谢

马丁·奥谢


为了澄清关于连接池方法的一点,我在应用程序中使用的不是Oracle,而是我自己的一个类,如下所示:

package myDataSharer.database_access;

import java.sql.*;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;

public class ConnectionPool_DBA {

    static Logger logger = Logger.getLogger(ConnectionPool_DBA.class.getName());

    private static ConnectionPool_DBA pool = null;
    private static DataSource dataSource = null;


    public synchronized static ConnectionPool_DBA getInstance() {
        if (pool == null) {
            pool = new ConnectionPool_DBA();
        }
        return pool;
    }

    private ConnectionPool_DBA() {
        try {
            InitialContext ic = new InitialContext();
            dataSource = (DataSource) ic.lookup("java:/comp/env/jdbc/myDataSharer");
        }
        catch(Exception ex) {
            logger.error("Error getting a connection pool's datasource\n", ex);
        }
    }

    public void freeConnection(Connection c) {
        try {
            c.close();
        }
        catch (Exception ex) {
            logger.error("Error terminating a connection pool connection\n", ex);           
        }
    }

    public Connection getConnection() {
        try {
            return dataSource.getConnection();
        }
        catch (Exception ex) {
            logger.error("Error getting a connection pool connection\n", ex);            
            return null;
        }
    }    
}

我想提到Oracle是因为我使用了一个类似的名称。

我想知道为什么您在代码中使用ConnectionPool\u DBA,而不是让Tomcat处理池并简单地使用JNDI查找连接

为什么要在MySQL中使用Oracle连接池?当我进行JNDI查找和连接池时,我更喜欢ApacheDBCP库。我发现它工作得很好

我还想问一下DatabaseUtils方法是否抛出任何异常,因为如果在调用pool.freeConnection()之前的任何一个调用抛出一个异常,您将永远无法释放该连接

我不太喜欢您的代码,因为执行SQL操作的类应该将其连接实例传递给它,而不应该承担获取和使用连接的双重责任。持久性类无法知道它是否正在更大的事务中使用。最好有一个单独的服务层来获取连接、管理事务、封送持久性类,并在完成时进行清理

更新:


谷歌找到了与你同名的甲骨文类。现在我真的不喜欢你的代码,因为你自己写了一些东西,而一个更好的选择很容易得到。我会马上放弃你的建议,并使用DBCP和JNDI重新进行此操作。

有一些关于避免这种情况的建议,这些建议是从其他来源获得的,特别是从其他驱动程序的连接池实现和其他应用服务器获得的。关于JNDI数据源的Tomcat文档中已经提供了一些信息

  • 建立清理/收割计划,如果池中的连接在某个时间段后处于非活动状态,则该计划将关闭这些连接。将与数据库的连接保持打开状态8小时(MySQL默认设置)不是一个好做法。在大多数应用程序服务器上,非活动连接超时值是可配置的,通常小于15分钟(即,连接不能留在池中超过15分钟,除非它们被反复使用)。在Tomcat中,当使用JNDI数据源时,执行相同的操作
  • 当新连接从池返回到应用程序时,请确保首先对其进行测试。例如,我所知道的大多数应用服务器都可以进行配置,以便通过执行“SELECT 1 FROM dual”来测试与Oracle数据库的连接。在Tomcat中,使用validationQuery属性为MySQL设置适当的查询-我相信这是“选择1”(不带引号)。设置validationQuery属性的值之所以有帮助,是因为如果查询无法执行,将从池中删除连接,并在其位置创建新连接
  • 就应用程序的行为而言,用户可能第一次看到池返回到应用程序的陈旧连接的结果。第二次,池可能会返回一个不同的连接,该连接可以为应用程序的查询提供服务


    Tomcat JNDI数据源基于Commons DBCP,因此适用于DBCP的数据源也将适用于Tomcat。

    web服务器和数据库之间是否有一个路由器可以透明地关闭空闲TCP/IP连接


    如果是这样,您必须让连接池放弃池中超过XX分钟未使用的连接,或者每YY分钟对连接执行某种ping操作以保持其活动状态。

    此错误表示服务器意外关闭连接。这可能发生在以下两种情况下

  • MySQL在特定时间后关闭空闲连接(默认为8小时)。发生这种情况时,没有线程负责关闭连接,因此连接会过时。如果此错误仅在长时间空闲后发生,则这很可能是原因

  • 如果没有完全读取所有响应,连接可能会在繁忙状态下返回到池。下一次,一个命令被发送到MySQL,它关闭了错误状态的连接。如果错误发生得相当频繁,这可能就是原因

  • 同时,设置逐出线程将有助于缓解问题。在数据源中添加类似的内容

              ...
              removeAbandoned="true"
              removeAbandonedTimeout="120"
              logAbandoned="true"
              testOnBorrow="false"
              testOnReturn="false"
              timeBetweenEvictionRunsMillis="60000"
              numTestsPerEvictionRun="5"
              minEvictableIdleTimeMillis="30000"
              testWhileIdle="true"
              validationQuery="select now()"
    

    很可能你还没有找到答案,这是我最后一天一直在处理的事情。我基本上在做与您相同的事情,只是我的池基于apache.commons.pool。与您看到的EOF完全相同的错误。检查mysqld错误日志文件,该文件很可能位于数据目录中。寻找mysqld崩溃。mysqld_safe会在mysqld崩溃时快速重启,因此除非查看其日志文件,否则情况不会明显/var/log对此场景没有帮助

    康奈克