oracle.jdbc.ReadTimeout导致Oracle连接池JDBC7

时间:2017-06-27 01:11:51

标签: java oracle jdbc

我目前正在尝试在JVM级别为数据库操作添加超时。我尝试添加 oracle.jdbc.ReadTimeout 并使用慢查询对其进行测试。它工作正常,操作确实抛出了一个 java.sql.SQLRecoverableException:IO错误:Socket读取超时,当操作达到超时时如预期。但后来我发现在连接超时后,这些连接不会重新检入连接池。它们被计为已检出的连接,并保存在已检出的连接列表中( OracleImplicitConnectionCache.checkedOutConnectionList )。池中此类不可用连接的持续增长最终将填满池,直到达到连接池的最大限制时不再发出连接。

即使将这些连接重新签入池中也没有意义,因为它们已经关闭并在 oracle.jdbc.internal.OracleConnection 类中标记为isUsable = false。理想情况下,这些连接应该从池中完全删除。因此,如果有人能够为我提供一些关于跟进的澄清,那就表示赞赏。

  1. 如果我们使用 oracle.jdbc.ReadTimeout ,有没有办法驱逐在读取超时后收集在连接池中的不可用连接?
  2. 是否有其他方法可以在JVM级别为数据库操作指定读取超时? 请注意 java.sql.Statement.setQueryTimeout(int timeout)也不是一个选项,因为我们必须为每个查询设置它
  3. 如果有人能为我提供一些帮助,我真的很感激。

    以下是上述方案的示例代码,

    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)
    

    此异常后恢复过程中止

0 个答案:

没有答案