Glassfish连接池 - java.sql.SQLException:连接已关闭

时间:2014-07-28 12:47:55

标签: jsf-2 jdbc oracle11g connection-pooling glassfish-4

我正在使用带有 Oracle Glassfish服务器开源版4.0 Oracle数据库11g(版本11.2.0-1.0)的Web项目JSF2。 服务器和数据库在同一台Windows机器上运行。 连接池管理与数据库的连接。

有人知道为什么我有时会遇到以下异常:

java.sql.SQLException: Connection closed
    at com.sun.gjc.spi.base.ConnectionHolder.checkValidity(ConnectionHolder.java:766)
    at com.sun.gjc.spi.base.ConnectionHolder.commit(ConnectionHolder.java:243)
    at de.mydomain.myproject.Hl7MessageHandler.run(Hl7MessageHandler.java:123)
    ...

或者有时这个:

java.sql.SQLRecoverableException: Closed connection
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:5675)
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:5735)
    at com.sun.gjc.spi.base.ConnectionHolder.commit(ConnectionHolder.java:244)
    at de.mydomain.myproject.Hl7MessageHandler.run(Hl7MessageHandler.java:123)
    ...

数据库类:

public static Connection getConnection() throws NamingException, SQLException {     
    Context initContext = new InitialContext(); 
    DataSource datasSource = (DataSource)initContext.lookup("jdbc/Oracle"); 
    Connection connnection = datasSource.getConnection();
    return connnection; 
}

servlet中的请求处理:

public IResponseSendable<String> run(String hl7MsgString, boolean publishErrorToDB) {

    // ... do something

    try {
        con = Database.getConnection();
    } catch (NamingException | SQLException conExc) {

        return generateAck(true, conExc.getMessage(), hl7MsgString);        
    }

    try {
        con.setAutoCommit(false); 
        process();
        con.commit();
    } catch (HL7Exception | SQLException pe) {
        logger.error(...);

        // Exceptionhandling...

        try { 
            con.rollback();
        } catch (SQLException rollbackExc) { 
            logger.error(...);
        }           
        return generateAck(true, pe.getMessage(),hl7MsgString, _log);
    }
    finally {

        try { 
            con.setAutoCommit(true);
            con.close();
        } catch (SQLException e) { 
            logger.error(...);
        }
    }
    return generateAck(false, "", hl7MsgString);
}

流程 - Methode:

private void process() throws HL7Exception, SQLException {
    // Do something...

    String sql = "BEGIN save_patient_data(?,?,?,?,?,?,?); END;";

    CallableStatement stmt = (CallableStatement) con.prepareCall(sql);
    stmt.setString(1, ...);
    // ...

    stmt.registerOutParameter(6, java.sql.Types.VARCHAR);
    stmt.registerOutParameter(7, java.sql.Types.NUMERIC);
    stmt.execute(); 
    // ... 
    stmt.close();

    // More databse stored procedure can be called ...
}

连接池设置:

Initial and Minimum Pool Size: 10 Connections
Maximum Pool Size: 60 Connections
Pool Resize Quantity: 2 Connections
Idle Timeout: 600 Seconds
Max Wait Time: 0 Milliseconds

Validate At Most Once: 0 Seconds
Connection Leak Timeout: 10 Seconds
Connection Leak Reclaim: enabled
Statement Leak Timeout: 6 Seconds
Statement Leak Reclaim: enabled
Creation Retry Attempts: 0
Retry Interval: 10 Seconds

Connection Validation: Required
Validation Method: meta-data

数据库IDLE-Timeout设置为“ UNLIMITED ”。

Notcie: 调用“con.prepareCall(sql);”时发生异常(不得在第一次)或当我尝试提交连接时或稍后何时尝试启用自动提交。

是否有任何机构知道调试应用程序以找出它的原因或最佳方法是什么?

谢谢。


编辑: 也许这很重要: 我可以在服务器日志中找到关于连接泄漏的许多警告:

2014-07-28T14:49:17.961+0200|Warnung: A potential connection leak detected for connection pool OraclePool. The stack trace of the thread is provided below : 
com.sun.enterprise.resource.pool.ConnectionPool.setResourceStateToBusy(ConnectionPool.java:324)
com.sun.enterprise.resource.pool.ConnectionPool.getResourceFromPool(ConnectionPool.java:758)
com.sun.enterprise.resource.pool.ConnectionPool.getUnenlistedResource(ConnectionPool.java:632)
com.sun.enterprise.resource.pool.AssocWithThreadResourcePool.getUnenlistedResource(AssocWithThreadResourcePool.java:200)
com.sun.enterprise.resource.pool.ConnectionPool.internalGetResource(ConnectionPool.java:526)
com.sun.enterprise.resource.pool.ConnectionPool.getResource(ConnectionPool.java:381)
com.sun.enterprise.resource.pool.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:245)
com.sun.enterprise.resource.pool.PoolManagerImpl.getResource(PoolManagerImpl.java:170)
com.sun.enterprise.connectors.ConnectionManagerImpl.getResource(ConnectionManagerImpl.java:360)
com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:307)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:196)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:171)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:166)
com.sun.gjc.spi.base.AbstractDataSource.getConnection(AbstractDataSource.java:114)
de.mydomain.myproject.utilities.Database.getConnection(Database.java:17)
...

1 个答案:

答案 0 :(得分:0)

您启用了连接泄漏回收,连接泄漏超时为10秒。这意味着如果您保持逻辑连接的时间超过10秒,则会被连接池管理器强制撤销并关闭(并且物理连接将返回到连接池)。 SQLException。

找出哪个操作的时间超过10秒,并尝试减少配置更长的连接泄漏超时所需的时间(10秒是恕我直言,连接泄漏检测有点短)。同样的BTW适用于您的语句泄漏检测(6秒也很短)。