java – Oracle PoolDataSource将数据库游标保持打开直到commit(),这是预期的行为吗?

除非我调用Connection.commit(),否则数据库游标在查询后仍保持打开状态.我相信这种行为导致我的应用程序泄漏游标并遇到与游标使用相关的数据库错误.似乎commit()调用应该是不必要的……是否需要这种行为?有没有办法...

除非我调用Connection.commit(),否则数据库游标在查询后仍保持打开状态.我相信这种行为导致我的应用程序泄漏游标并遇到与游标使用相关的数据库错误.

似乎commit()调用应该是不必要的……是否需要这种行为?有没有办法配置JDBC连接池,以便在资源关闭时可靠地释放游标,而无需调用commit?

我正在使用此查询来查找打开的游标:

从v $open_cursor中选择*,其中CURSOR_TYPE =’OPEN’

如果在关闭语句和ResultSet之后调用commit(),则在sleep()期间不会打开游标

   try (Connection con = pooledDataSource.getConnection()) {
        try (PreparedStatement statement = con.prepareStatement("select 1 from dual a");
             ResultSet rs = statement.executeQuery()) {
        }
        con.commit();
    }

    Thread.sleep(20000);

如果我在关闭语句和ResultSet之前调用commit,当我在sleep()期间查询open游标时,我发现s中的sql select 1.

        try (Connection con = pooledDataSource.getConnection();
             PreparedStatement statement = con.prepareStatement("select 1 from dual b");
             ResultSet rs = statement.executeQuery()) {{

             con.commit();
        }}

        Thread.sleep(20000);

这里也是一样的.如果我不调用commit(),我会在我的打开游标查询中找到`select 1 from dual c,它在JVM退出之前一直保持打开状态.

        try (Connection con = pooledDataSource.getConnection();
                PreparedStatement statement = con.prepareStatement("select 1 from dual c");
                ResultSet rs = statement.executeQuery()) {{
        }}

这些是我的配置

        PoolDataSource pooledDataSource = PoolDataSourceFactory.getPoolDataSource();
        pooledDataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
        pooledDataSource.setURL("jdbc:oracle:thin:@//" + host + ":1521/" + service);
        pooledDataSource.setUser(user);
        pooledDataSource.setPassword(pw);
        pooledDataSource.setInitialPoolSize(1);
        pooledDataSource.setMinPoolSize(1);
        pooledDataSource.setMaxPoolSize(1);
        pooledDataSource.setAbandonedConnectionTimeout(5);
        pooledDataSource.setConnectionWaitTimeout(5);
        pooledDataSource.setInactiveConnectionTimeout(5);

解决方法:

使用以下测试UCPTest.java,此行为不会在12.2.0.1(JDBC Download page)中重现.无论如何请注意,这不是错误.你观察到的是因为当一个陈述被关闭时,司机没有进行往返.相反,该操作将在下一次往返时捎带.这是一种优化,可以减少客户端和服务器之间的往返总数.您在12.2.0.1中没有观察到相同行为的原因是因为当连接释放到池并且刷新搭载调用时,UCP会对数据库进行单向访问.如果你想人为地冲洗背驮式电话,你也可以这样做
((oracle.jdbc.OracleConnection)con).pingDatabase()这是一个完整的往返,因此携带了搭载呼叫的队列.

本文标题为:java – Oracle PoolDataSource将数据库游标保持打开直到commit(),这是预期的行为吗?

基础教程推荐