我目前正在尝试在JVM级别为数据库操作添加超时。我尝试添加 oracle.jdbc.ReadTimeout 并使用慢查询对其进行测试。它工作正常,操作确实抛出了一个 java.sql.SQLRecoverableException:IO错误:Socket读取超时,当操作达到超时时如预期。但后来我发现在连接超时后,这些连接不会重新检入连接池。它们被计为已检出的连接,并保存在已检出的连接列表中( OracleImplicitConnectionCache.checkedOutConnectionList )。池中此类不可用连接的持续增长最终将填满池,直到达到连接池的最大限制时不再发出连接。
即使将这些连接重新签入池中也没有意义,因为它们已经关闭并在 oracle.jdbc.internal.OracleConnection 类中标记为isUsable = false。理想情况下,这些连接应该从池中完全删除。因此,如果有人能够为我提供一些关于跟进的澄清,那就表示赞赏。
如果有人能为我提供一些帮助,我真的很感激。
以下是上述方案的示例代码,
public static void main( String[] args )
{
try
{
System.setProperty( "oracle.jdbc.ReadTimeout", "2000" );
checkTimeOut();
Thread.sleep( 4000 );
String answer = getUserInput();
while( answer.toUpperCase().startsWith( "Y" ) )
{
checkTimeOut();
Thread.sleep( 4000 );
answer = getUserInput();
}
}
catch( Exception e )
{
e.printStackTrace();
}
}
private static String getUserInput()
{
String answer = "";
try
{
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
System.out.println( "Continue?" );
answer = br.readLine();
}
catch( IOException e )
{
e.printStackTrace();
}
return answer;
}
private static void checkTimeOut()
{
Connection con = null;
PreparedStatement ps = null;
Date time = null;
try
{
time = new Date();
String sql = "";//slow query here
con = PoolFactory.getConnectionPool( "ORACLE" ).getConnection();
con.setAutoCommit( false );
ps = con.prepareStatement( sql );
ps.executeUpdate();
commit( con );
System.out.println( "Successfully Updated" );
System.out.println( new Date().getTime() - time.getTime() );
}
catch( SQLException e )
{
System.out.println( "Failed to Update" );
System.out.println( new Date().getTime() - time.getTime() );
e.printStackTrace();
rollback( con );
}
finally
{
close( ps );
close( con );
}
}
private static void close( PreparedStatement ps )
{
if( ps != null )
{
try
{
ps.close();
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
private static void commit( Connection con )
{
if( con != null )
{
try
{
con.commit();
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
private static void rollback( Connection con )
{
if( con != null )
{
try
{
con.rollback();
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
private static void close( Connection con )
{
if( con != null )
{
try
{
con.close();
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
当我设置 AbandonedConnectionTimeout = 2 时,后台线程 OracleImplicitConnectionCacheThread 将尝试恢复放弃超过 2秒的连接。但是由于以下异常,此线程无法恢复这些超时连接。
java.sql.SQLRecoverableException: Closed Connection
at oracle.jdbc.driver.PhysicalConnection.getAutoCommit(PhysicalConnection.java:2254)
at oracle.jdbc.OracleConnectionWrapper.getAutoCommit(OracleConnectionWrapper.java:138)
at oracle.jdbc.pool.OracleImplicitConnectionCache.closeCheckedOutConnection(OracleImplicitConnectionCache.java:1395)
at oracle.jdbc.pool.OracleImplicitConnectionCacheThread.runAbandonedTimeout(OracleImplicitConnectionCacheThread.java:251)
at oracle.jdbc.pool.OracleImplicitConnectionCacheThread.run(OracleImplicitConnectionCacheThread.java:80)
此异常后恢复过程中止