使用OracleDataSource与OCI驱动程序进行过时连接

时间:2011-05-11 14:39:46

标签: java jdbc oracle10g connection-pooling oci

当我的Java应用程序没有向数据库发出几个小时的请求时,我收到过时的连接错误。

它是一个简单的Java应用程序,在带有OCI(类型驱动程序)的Linux机器上运行。不要问我为什么OCI,为什么不瘦。我使用OracleDataSourceOracleConnectionCacheManager来维护连接对象的缓存。以下是代码段:

import java.sql.Connection; 
import java.sql.SQLException; 
import java.util.Properties; 

import oracle.jdbc.pool.OracleConnectionCacheManager; 
import oracle.jdbc.pool.OracleDataSource; 

import org.apache.log4j.Logger; 

import com.exception.DataException; 

public class ConnectionManager { 
private static OracleDataSource poolDataSource = null; 
private final static String CACHE_NAME = "CONNECTION_POOL_CACHE"; 
private static OracleConnectionCacheManager occm = null; 

public static void init(String url,String userId,String password) throws PCTDataException{ 
Properties cacheProps = null; 
try { 
poolDataSource = new OracleDataSource(); 
poolDataSource.setURL(url); 
poolDataSource.setUser(userId); 
poolDataSource.setPassword(password); 

cacheProps = new Properties(); 
cacheProps.setProperty("MinLimit", "1"); 
cacheProps.setProperty("MaxLimit", "5"); 
cacheProps.setProperty("InitialLimit", "1"); 
cacheProps.setProperty("ValidateConnection", "true"); 

poolDataSource.setConnectionCachingEnabled(true); 
occm = OracleConnectionCacheManager.getConnectionCacheManagerInstance(); 
occm.createCache(CACHE_NAME, poolDataSource, cacheProps); 
occm.enableCache(CACHE_NAME); 
} catch (SQLException se) { 
throw new DataException("SQL Exception while initializing connection pool"); 
}catch(Exception e){ 
throw new DataException("Exception while initializing connection pool"); 
} 
} 

public static Connection getConnection() throws PCTDataException { 
try{ 
if (poolDataSource == null) { 
throw new SQLException("OracleDataSource is null."); 
} 
occm.refreshCache(CACHE_NAME, OracleConnectionCacheManager.REFRESH_INVALID_CONNECTIONS); 
Connection connection = poolDataSource.getConnection(); 
return connection; 
}catch(SQLException se){ 
se.printStackTrace(); 
throw new DataException("Exception while getting Connection object"); 
}catch(Exception e){ 
e.printStackTrace(); 
throw new DataException("Exception while getting Connection object"); 
} 
} 

public static void closePooledConnections() { 
try{ 
if (poolDataSource != null) { 
poolDataSource.close(); 
} 
}catch(SQLException se){ 
}catch(Exception e){ 
} 

} 
} 

错误如下:

ConnectionManager.java:getConnection:87 - Exception while getting Connection object: 
java.sql.SQLException: Invalid or Stale Connection found in the Connection Cache 
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) 
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) 
at oracle.jdbc.pool.OracleImplicitConnectionCache.getConnection(OracleImplicitConnectionCache.java:390) 
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:404) 
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:189) 

我错过了什么?

3 个答案:

答案 0 :(得分:1)

也许你需要设置保持活力?这样做是定期的,当不使用时,它发送ping到数据库服务器基本上说我还在这里,不要关闭我。尽管尝试调试并不是那么有趣。问题可能是数据库服务器上的设置,其中存在最大连接时间或杀死空闲连接的时间。您可以使用池中的一些设置来检查这一点,然后告诉它在发生这种情况时获得一个新设置。我希望我可以提供更多帮助,但我没有与oracle合作过。

答案 1 :(得分:1)

我建议使用专门用于缓存OCI连接的OracleOCIConnectionPool,而不是使用OracleDataSource + OracleConnectionCacheManager。

除了OracleDataSource的PoolConfig属性和OracleOCIConnectionPool有点不同之外,它是OracleDataSource的替代品。

答案 2 :(得分:0)

如果连接池中的连接不再主动连接到数据库,则会出现“无效或过时连接”错误。以下是可能导致此问题的几种情况

  1. 通过dba手动中断数据库连接。例如,如果 使用“ALTER SYSTEM KILL SESSION”
  2. 杀死连接
  3. 当连接池中存在连接而未用于连接时 由于强制执行超时而导致长时间断开连接 数据库(idle_time)
  4. 数据库重启
  5. 网络事件造成的 连接丢弃,可能是因为网络已成为 不可用或防火墙已经断开连接 打开太久了。
  6. 运行以下查询以确定数据库强制执行的IDLE_TIME

    select * from dba_profiles dp, dba_users du
    where dp.profile = du.profile and du.username ='YOUR_JDBC_USER_NAME';
    

    现在尝试使用以下配置

    Properties cacheProps = new Properties(); 
    cacheProps.setProperty("MinLimit", "0"); 
    cacheProps.setProperty("MaxLimit", "5"); 
    cacheProps.setProperty("InitialLimit", "1"); 
    cacheProps.setProperty("ValidateConnection", "true");
    cacheProps.setProperty("InactivityTimeout", "17000"); //something lower than the DB IDLE_TIME
    cacheProps.setProperty("PropertyCheckInterval", "16000") /*something lower than the inactivity timeout
     - to make sure that connections which were inactive for more than InactivityTimeout
     are always removed from the pool*/