>pstmt.setInt(1, 422);
>ResultSet rs = pstmt.executeQuery();
// processing of result set
>pstmt = dbCon.prepareStatement("select * from customers where >cust_id = ?");
上面这段代码存在Statement泄露的bug.第一次创建的pstmt没有被关闭,它的handler就reference到新的statement 实例。我们并无这样的问题。
我们的游标过多问题确实是这样解决的
会不会是有些code没留意?你的cursor全部对应存储过程么?
ResultSet作为返回值,很难判断什么时候会被关闭。
|
一旦发现连接生命周期超限或者调用次数超限,就在数据库连接持关闭这个连接,一旦连接被关闭,那么其游标也就释放了
我们的系统按照这个算法,稳定性(服务器不因为游标问题而当掉)由原来的1天提高到了1周
Oralce游标分为显示游标和隐式游标两种:
两种游标都会在v$open_cursor中体现出来。
但是两种游标是由区别的:
隐式游标大部分创建是通过存储过程来的,例如在存储过程中Select 一个查询,就会打开一个隐式游标,这时在Open_cusor中会有纪录。而这种游标不会随着CallableStatement对象的关闭而关闭。他会一直停留在高速缓存中。这也是为什么存储过程执行起来要快很多的原因之一。只有当打开的游标数大于你所设定的打开的最大游标数时才会按照一定的算法吧高速缓存中的隐式游标关闭调。最大游标数设定是在系统参数中设定的。oracle8i缺省好像每个连接为300个。这样的游标只会提高行能而不会降低性能。
显示的游标就更好解释了,例如你用JDBC创建一个statement,preparestatement,执行一些查询语句,每执行一个查询就会打开一个显示游标。关闭Statement就会关闭这些游标,如果你没有关闭,那么显示游标数将会增加,当打开的游标数大于最大游标数时就会检查有没有隐士游标,如果有则剔除掉让给显示游标。当显示游标的最大数目超过最大值时则汇报错:超出最大允许打开游标数的错误。
所以只要你保证所有的Statement都关闭了就不会有问题。
|
这样只有最后一次的游标被释放了。希望你们不会犯这样的错误,只是白提醒一下。
ResultSet rs = null;
ptmt = conn.prepareStatement();
for ()
{
rs = ptmt.excuteQuery();
}
rs.close();
也可能这个问题跟connection pool的实现有一定关系!
但是我碰到由于使用CallableStatement调用Oracle的Procedure而导致Procedure中的游标无法关闭,使用“select sid, sql_text, count(*) from sys.v_$open_cursor group by sid, sql_text”发现每执行一次就新增若干个游标,但是在源码方面已经将CallableStatement给Close了。由于使用了ConnetionPool,对于Connection不方便显式的Close,那么是否在Oracle服务器端可以配置释放Procedure中打开的游标呢?还是在JDBC中可以控制?