ORA-01000: 超出打开游标的最大数(解决及原因)

441 篇文章 1 订阅

还是 chongqingdaxue 缴费平台税票打印完毕上传到财务处时当税票数目较少时(10几张)能正常上传;当数目较大时(408), 就上传失败查看 tomcat 日志如下:

clip_image001[4]

既然超出最大游标数为了第一间让程序恢复正常运行当然"脚疼治脚"先把最大游标数调大:

(1).  DBA 登录 PL/SQL

(2). 打开 Command Window(注意不是 SQL Window)

clip_image002[4]

(3). 输入以下命令修改 oracle 最大游标数为 1000

1 SQL> alter system set open_cursors=1000 scope=both;

(4). 查看最大游标数是否已修改成功

1 SQL> show parameter open_cursors;

(5). 重启 tomcat(一定要有这一步否则修改不生效)

 

经过以上操作票据顺利上传上去了可是这样治标不治本万一以后来个1000张以上的票据要上传那不就又得改游标数了; 在代码里肯定是每处理一张票就打开一个游标的这样是错误的网上找了这个错误代码的相关说明, 在这里发现以下这段话

这样的错误很容易出现在Java代码中的主要原因是:Java代码在执行conn.createStatement()和 conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。尤其是,如果你的 createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。


在代码里看了一下果然是这样, 程序通过循环调用封装好的 executeSql 函数, 来对每张票进行 update, 而 executeSql 里每次都调用了 conn.prepareStatement(); 将其移出循环再改回原游标数再上传票据就不再报错了.

01 public static void executeSql(Connection conn, String sql, Object[] parValue) throws Exception{
02     PreparedStatement ps = null;
03     try {
04         LOGGER.info(sql);
05         ps = conn.prepareStatement(sql);
06         if (parValue != null){
07             String params = "";
08             for (int i = 0; i < parValue.length; i++){
09                 if (i != 0){
10                     params += ",";
11                 }
12                 ps.setObject(i+1, parValue[i]);
13                 params += parValue[i];
14             }
15             LOGGER.info(params);
16         }
17         ps.execute();
18     catch (SQLException e) {
19         e.printStackTrace();
20         throw new Exception();
21     finally {
22         if (ps != null){
23             ps.close();
24         }
25     }
26 }

注: 原代码有进行 ps.close(); 但是仍然无效是因为 connection 的 autocommit 设为 false 的原因? 还是因为 connection 是从连接池取的原因呢?

这里有一个问题说明 connection 与 prepareStatement 进行 close 的关系, 但这里只是说明了直接 close connection, 而没有说明直接 close prepareStatement.

问:

用CONNECTION 创建了 PREPAREDSTATEMENT ,用完了 PREPAREDSTATEMENT 后,没有关闭PREPAREDSTATEMENT ,而是直接 CLOSE CONNECTION ,这么做有什么隐患吗?

答:

如果没有使用数据库连接池,而是每次创建物理连接,然后释放的话,没有什么问题。close Connection的时候已经把数据库资源完全释放掉了,PreparedStatement占用的数据库游标也会随即释放。 但是大部分情况读写数据库都会采用数据库连接池来提高连接效率,在这种情况下有潜在的隐患。 因为数据库连接池中拿到一个Connection,close的时候不是真正关闭连接,释放数据库资源,而是把连接归还给连接池。因此在这种情况下,close了Connection,但是PreparedStatement并没有被释放掉,占用的数据库游标仍然处于打开状态。因此在大数据访问量的情况下很容易出现数据库游标使用到最大,无法分配游标错误。


 环境: Oracle 10g

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值