碰到一个jdbc游标超出最大数的异常。正好对Oracle与jdbc关系做了进步了解。记录下以便日后查阅,有错误之处,欢迎大家指出。
Oralce游标分为显示游标和隐式游标两种:
两种游标都会在v$open_cursor中体现出来。
但是两种游标是由区别的:
隐式游标大部分创建是通过存储过程来的,例如在存储过程中Select 一个查询,就会打开一个隐式游标,这时在Open_cusor中会有纪录。而这种游标不会随着CallableStatement对象的关闭而关闭。他会一直停留在高速缓存中。这也是为什么存储过程执行起来要快很多的原因之一。只有当打开的游标数大于你所设定的打开的最大游标数时才会按照一定的算法吧高速缓存中的隐式游标关闭调。最大游标数设定是在系统参数中设定的。oracle8i缺省每个连接为300个。这样的游标只会提高行能而不会降低性能。
显示的游标就更好解释了,例如你用JDBC创建一个statement,preparestatement,执行一些查询语句,每执行一个查询就会打开一个显示游标。关闭Statement就会关闭这些游标,如果你没有关闭,那么显示游标数将会增加,当打开的游标数大于最大游标数时就会检查有没有隐士游标,如果有则剔除掉让给显示游标。当显示游标的最大数目超过最大值时则汇报错:超出最大允许打开游标数的错误。 所以只要你保证所有的Statement都关闭了就不会有问题。
同时系统将结束此次会话,释放所有的cursor。JDBC标准规定了在释放连接的时候必须statement.close....
注意: 对于使用连接池技术,只是将连接返回到连接池。如果没有返回连接的时候关闭statement,resultset资源,会导致游标超出最大数
Exception : java.sql.SQLException: ORA-01000: maximum open cursors exceeded
1. getConnection相当于打开一个数据库session,
查看session 语句:select * from v$session ss where ss.USERNAME='ISKK_TEST'
2. statement,prepareStatement,callableStatement 获取一个游标,此时并不会在v$open_cursor 里出现,execute之后才打开一个cursor,这时候在v$opent_cursor可以查询的到。
select COUNT(*) from v$open_cursor o
where o.USER_name='ISKK_TEST'
order by o.LAST_SQL_ACTIVE_TIME desc
3. 查看每个连接的最大游标数
show parameter session_cached_cursors;
4. 查看session缓存的最大游标数
show parameter session_cached_cursors;
ojdbc14.jar(oracle10.2) 测试结果:
循环执行相同的语句,只会使用一个cursor,并不会产生新cursor循环执行不同的语句, 会有多个cursor产生。