ORA-1000: max cursor exceeded.
可以在 v$open_cursor中查询未关闭的cursor.
最好还是用完就关。
但问题是:是不是正如oldma所说的那样,我们也可以把DB端的资源回收当作黑盒(或者一个能自我调整的容器)来看待,而不必去关心它的溢出或者阻塞???正如我们现在经常使用的连接池pool一样!!
1)如果是这样的,那么我们可以只处理connection的关闭,因为connection的关闭会自动引起java端的rs、st和pst的关闭,而在DB端,则有cache可以复用这些未被显式释放的cursor资源,使这些资源不至于被挂起;
2)如果不是这样,那么我们必须手工关闭rs、st和pst这些与数据库资源对应的对象来释放DB端的资源,然后在最后关闭conn,因为DB不会聪明地调度这些被挂起的资源,不主动关闭它们会导致DB资源被耗尽。
通过回答这一问题,请大家告诉我,我在发帖的时候写的那个函数在极度频繁被调用时可行吗?因为这个函数不处理任何close()操作,只是根据调用者的connection参数和String参数返回rs给调用者,在调用者的代码的最后会有rs.close()和connection.close()操作,但是肯定不会有st.close()。 那么这个未被显式地close()的st就是我一直不清楚的东西,在非常频繁地被重复这样调用(事实上这样的调用就象out.print()一样多)后,DB端会是怎样一种情况?
还有我前面说了,几种情况:
1、ResultSet不依赖于Connection和Statement,这样你只需要一个Connection和一个Statement,这样你每次可以充用这两个对象,那么你只需要和Connection一样加上对Statement的关闭就可以了,中间的使用者必须自己关闭ResultSet
2、ResultSet依赖于Connection和Statement,这样你必须小心设计中间的过程,在同一个命名空间里不能同时建立两个ResultSet对象。
3、ResultSet依赖于Statement对象,但不依赖于Connection对象,这样,你不关闭Statement可能和第一种情况下不关闭ResultSet一样。
但是我有个疑惑,根据JAVA DOC,Connection、Statement、ResultSet应该都会在垃圾收集时自动被释放。因此理论上他们不应该会存在资源泄漏问题。可能显式的调用Connection的close能够更快的释放数据库资源,但我认为使用Connection Pool应该是更有效率的做法。但对使用Connection Pool的情况下,是否必须显式的close Connection?Statement和ResultSet应该没有必要显式的释放吧,至少从来没有听说有Statement Pool和ResultSet Pool,这是否意味着他们并不使用DB资源呢?
一切只是我的推测,希望有高人能够提出一个可信的测试方案来推翻或是验证它。
摘录自 JDBC. 3.0 Specification,13.1.3 Closing Statement Objects
An application calls the method Statement.close to indicate that it has finished processing a statement. All Statement objects will be closed when the connection that created them is closed. However, it is good coding practice for applications to close statements as soon as they have finished processing them. This allows any external resources that the statement is using to be released immediately.
Closing a Statement object will close and invalidate any instances of ResultSet produced by that Statement object. The resources held by the ResultSet object may not be released until garbage collection runs again, so it is a good practice to explicitly close ResultSet objects when they are no longer needed.
These comments about closing Statement objects apply to PreparedStatement and CallableStatement objects as well.
public static ResultSet sysSelect(Connection conn,String sql)throws SQLException{
Statement st = null;
try{
st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
return rs;
}catch (SQLException ex){
throw ex;
}finally{
if (null!=st) st.close();
}
}
finally中的st.close()会导致它所产生的resultset实例无效,也就是说方法返回参数的rs在该方法执行完毕的时候就是无效的。不知道我的想法对不对。
我个人认为:在一个大吞数据吐量和访问率的信息系统中,其健壮性除了使用某种先进的API库或者架构之外,关键之处在于代码的编写习惯、或者是我们经常使用到的、看似可有可无的某些代码的编写方式上!
to glassprogrammer: 关闭连接后还能使用rs的讨论,我在其他地方看到过类似的讨论,可是我以前在DB2、ORACLE812上测试的结果都是行不通的!不知道你是在哪里设置了这一特性? 不过对于使用conn.createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)的最后一个参数可以做到这一点! 但是这是jdbc3.0里的功能,我现在所在的都是IBM的环境,IBM自带的JDK只相当于sun jre1.3.1的版本,是没有这个功能所以也无法测试。
to navyzhu :你肯定其他地方有问题.我做了试验
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
for (int i=0; i<100; i++){
Connection conn = DriverManager.getConnection(
"jdbc:microsoft:sqlserver://Akun:1433;databaseName=bookstore", "sa",
"");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery("Select * from Book");
//stm.close();
conn.close();
}
执行后,在SQL查询分析器里sp_who,不占连接啊.
一定要close掉ResultSet,否则资源会泄漏,因为ResultSet里有Stream对象,close才会调用Stream.close。至于mysapphire的问题,一个简单的方法就是再调用一下ResultSet.getStatement().close就可以了。不知道其他高手有何其他高见。