ggww
2004-07-14 09:18
JDBC中,Statment对应游标,关掉statement应该就可以.

dabb
2004-07-14 16:34
> PreparedStatement pstmt = dbCon.prepareStatement("select * >from emp where emp_id=?");
>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 实例。我们并无这样的问题。


IT民工
2004-07-15 16:12
谢谢,楼主!

missxkl
2004-07-16 09:07
建议你把典型的几处代码贴出来,不然很难判断

我们的游标过多问题确实是这样解决的

会不会是有些code没留意?你的cursor全部对应存储过程么?

peter_liu
2004-07-16 23:32
qq

cats_tiger
2004-07-19 09:10
用RowSet试试
ResultSet作为返回值,很难判断什么时候会被关闭。

ResultSet executeQuery(String sql){
  CachedRowSet rowSet = new CachedRowSet();
  ResultSet rs = null;
  Connection conn = null;
  Statement stmt = null;

  try{
    //数据库操作
    rowSet.populate(rs);
  }
  cacth( SQLException e){
  }
  finally{
   //关闭所有数据库资源,除了RowSet
  }
  
  return rowSet;
}
<p class="indent">

yinxchun
2004-07-21 10:01
对连接池连接加入生命周期和调用次数的控制
一旦发现连接生命周期超限或者调用次数超限,就在数据库连接持关闭这个连接,一旦连接被关闭,那么其游标也就释放了

我们的系统按照这个算法,稳定性(服务器不因为游标问题而当掉)由原来的1天提高到了1周

starry
2004-07-21 14:32
这个问题涉及到Oracle的游标管理问题:
Oralce游标分为显示游标和隐式游标两种:
两种游标都会在v$open_cursor中体现出来。

但是两种游标是由区别的:
隐式游标大部分创建是通过存储过程来的,例如在存储过程中Select 一个查询,就会打开一个隐式游标,这时在Open_cusor中会有纪录。而这种游标不会随着CallableStatement对象的关闭而关闭。他会一直停留在高速缓存中。这也是为什么存储过程执行起来要快很多的原因之一。只有当打开的游标数大于你所设定的打开的最大游标数时才会按照一定的算法吧高速缓存中的隐式游标关闭调。最大游标数设定是在系统参数中设定的。oracle8i缺省好像每个连接为300个。这样的游标只会提高行能而不会降低性能。
显示的游标就更好解释了,例如你用JDBC创建一个statement,preparestatement,执行一些查询语句,每执行一个查询就会打开一个显示游标。关闭Statement就会关闭这些游标,如果你没有关闭,那么显示游标数将会增加,当打开的游标数大于最大游标数时就会检查有没有隐士游标,如果有则剔除掉让给显示游标。当显示游标的最大数目超过最大值时则汇报错:超出最大允许打开游标数的错误。
所以只要你保证所有的Statement都关闭了就不会有问题。

starry
2004-07-21 14:47
在有就是,如果你的连接是没有问题的,那就应该思考一下你的程序设计。有可能的话用Debug工具看一下是那些对象在不断的增长这样会容易的找出内存泄漏地方。Jprobe还不错挺好用的,可以试一试

blueice
2004-07-21 17:16
我的同事犯过这样的低级错误:

ResultSet rs = null;
while(){
  PreparedStatement ps = conn.prepareStatement(...);
  rs = ps.executeQuery();
}
rs.close();
<p class="indent">

这样只有最后一次的游标被释放了。希望你们不会犯这样的错误,只是白提醒一下。

feed
2004-08-03 15:33
如果写成这样呢

ResultSet rs = null;
ptmt = conn.prepareStatement();
for ()
{
rs = ptmt.excuteQuery();
}
rs.close();

wabby
2004-08-13 15:11
这个问题我遇到过,可以肯定是oracle的bug,当时的平台是AIX+oracle8174,oracle9201,当使用websphere connection pool的时候,都存在这个问题,如果不使用pool,直接jdbc操作就没有问题,后来升级数据库到9205解决问题!
也可能这个问题跟connection pool的实现有一定关系!

wzbwambition
2004-08-19 17:25
把resultset返回到jsp绝对是个错误,建议把封装数据库的类重写,把数据放在hashmap,vector,arraylist里返回到jsp吧。jsp中千万别看到resultset等

sunny_ustb
2004-08-26 10:13
不知楼主是否已经解决了这个问题?关注中!我们现在的oracle9201也有些bug。

wkq2000
2004-09-16 14:14
对于由Statement、PreparedStatement而导致的‘显式’游标无法关闭问题是可以控制和解决的,使用一个类来提供OpenQuery,RunSQL等数据库一般操作的方法,在使用时要额外小心显式的关闭Statement,并且对于每个功能可以配合“select sid, sql_text, count(*) from sys.v_$open_cursor group by sid, sql_text”来查看是否存在有游标未关闭的情况(即Statement未关闭)。目前我是这样解决的,好像比较累:(
但是我碰到由于使用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中可以控制?

猜你喜欢