ORA-01000: maximum open cursors exceeded

 

 

clip_image001[4]

或者错误:ORA-01000: maximum open cursors exceeded

以上两种错误就表名oracle游标超出了最大值,客户端把连接oracle的光标用光了。

 

定位问题:Resultset,循环执行rs.next(),假如我的记录数很多,连接一致不断开,就会用光游标

 

 

这样的错误很容易出现在Java代码中的主要原因是:Java代码在执行conn.createStatement()和 conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。
尤其是,如果你的 createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。
我测试了一下,我的oracle游标默认是300,大概用rs.next()这种方式取5000条数据就会报错了。

 

 

解决方案:

(1). 以 DBA 登录 PL/SQL

 

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

SQL> show parameter open_cursors;

一般游标数为几百个,我的是300.

(3). 我们可以通过增大游标数,来解决此问题。

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

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

SQL> show parameter open_cursors;

问:

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

答:

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

 

如果你要用到Connection取记录,并且记录可能很多的话,请不要用druid连接池,请用传统jdbc方法,并且在每次循环结束后关闭Conn,这样就不会出现这个问题了。

 

    /**
     * 获取JDBC连接
     *
     * @param url
     * @param username
     * @param password
     * @return
     */
    private Connection getConnection(String url, String username, String password) {
        Connection conn = null;
        try {
            // 不需要加载Driver. Servlet 2.4规范开始容器会自动载入
            // conn = DriverManager.getConnection(url, username, password);
            //
            Properties info = new Properties();
            //
            info.put("user", username);
            info.put("password", password);
            conn = DriverManager.getConnection(url, info);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

 

posted @ 2020-07-03 11:20  Jerryi224  阅读(1595)  评论(0编辑  收藏  举报