除非我调用Connection.commit()
,否则查询后数据库游标将保持打开状态。我相信这种行为正在导致我的应用程序泄漏游标并遇到与游标使用相关的数据库错误。
似乎该commit()
呼叫应该是不必要的...是这种现象吗?有什么方法可以配置JDBC连接池,以便在关闭资源时可靠地释放游标,而无需调用commit?
我正在使用此查询来查找打开的游标:
select * from v$open_cursor where CURSOR_TYPE = 'OPEN'
如果我commit()
在关闭statement
和之后致电ResultSet
,则在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);
如果在close statement
和之前调用commit ResultSet
,则select 1 from b
在sleep()期间查询打开的游标时会找到sql 。
try (Connection con = pooledDataSource.getConnection();
PreparedStatement statement = con.prepareStatement("select 1 from dual b");
ResultSet rs = statement.executeQuery()) {{
con.commit();
}}
Thread.sleep(20000);
这里也是一样。如果不打电话,commit()
我会在打开的游标查询中从对偶c中选择“选择1”,该查询将一直保持打开状态,直到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下载页面)中重现此行为。无论如何,请注意,这不是错误。您观察到的原因是由于在关闭语句时驱动程序未进行往返。而是在下一次往返时背负该操作。这是减少客户端和服务器之间往返总数的优化。在12.2.0.1中未观察到相同行为的原因是,当连接释放到池中时,UCP进行了单向数据库访问,并刷新了背负调用。如果您想人为冲刷搭载呼叫,您也可以这样做,这是一次完整的往返,因此会携带搭载呼叫的队列。((oracle.jdbc.OracleConnection)con).pingDatabase()
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句