错误 ORA-01000: 超出最大打开游标

Posted

技术标签:

【中文标题】错误 ORA-01000: 超出最大打开游标【英文标题】:Error ORA-01000: maximum open cursors exceeded 【发布时间】:2017-02-24 14:26:05 【问题描述】:

在 Eclipse 中我收到此错误:**Error ORA-01000: maximum open cursors exceeded 我最终已经在块中关闭了连接,但我不知道为什么我会收到这个错误,这是我的代码 JAVA。 请帮帮我!

 for (DossierAMO dos = null; it.hasNext();) 
            PreparedStatement ps = null;
            ResultSet rs = null;
            PreparedStatement ps2 = null;
            ResultSet rs2 = null;
            try 
                dos = (DossierAMO) it.next();   
                //PreparedStatement ps = null;
                //ResultSet rs = null;
                /*try
                 * 
                */
                System.out.println("Imma"+dos.getImma());
                    ps = cnnOracle.getConnexion().prepareStatement(
                            "select count(IMM_IMM_V_NUM_IMM) from d_salaire@prod_dist where SAL_C_DS =21 and IMM_IMM_V_NUM_IMM =?",
                            ResultSet.TYPE_FORWARD_ONLY,
                            ResultSet.CONCUR_READ_ONLY
                            );
                    ps.setString(1,dos.getImma());
                    rs = ps.executeQuery();
                    if (rs.next())

                        if (rs.getInt(1) != 0)
                            //System.out.println("> Ecriture des dossiers d'indus dans le fichier d'indus2");
                            fichierIndius2.ecrireDossier(dos);
                        else
                        


                            ps2 = cnnOracle.getConnexion().prepareStatement(
                            "select count(DOS_N_NUM_DOS) from d_dossier@prod_dist where IMM_IMM_V_NUM_IMM =?",
                            ResultSet.TYPE_FORWARD_ONLY,
                            ResultSet.CONCUR_READ_ONLY
                            );
                            ps2.setString(1,dos.getImma()); 
                            rs2 = ps2.executeQuery();
                            if (rs2.next())

                            if (rs2.getInt(1) != 0)

                            fichierIndius2.ecrireDossier(dos);

                            else
                fichierIndius.ecrireDossier(dos);
        
             catch (Exception ex) 
                requete.fermer();

                fichierIndius.fermerSansException();
                fichierIndius2.fermerSansException();
                cnnAS400.fermerConnexion();
                cnnAS400FO.fermerConnexion();
                cnnOracle.fermerConnexion();
                System.err
                        .println("Erreur d'écriture dans le fichier d'indus! /        EXC : "
                                + ex);
                return;
            
            finally

                if (rs != null)
                    try 
                        rs.close();
                     catch (Exception exx) 
                    
                if (rs2 != null)
                    try 
                        rs2.close();
                     catch (Exception exx) 
                    
                if (ps != null)
                    try 
                        ps.close();
                     catch (Exception exx) 
                    
                if (ps2 != null)
                    try 
                        ps2.close();
                     catch (Exception exx) 
                    
            






        

【问题讨论】:

为什么将rsps 设置为null?这将阻止那些在 finally 块中被关闭。而且您尝试关闭ps 而不是ps2。你认为你什么时候关闭连接 - 因为你没有指向你打开的两个变量? (可能在异常处理程序中除外,具体取决于这些调用的作用。) Alex 我已经修改了这些行,但我仍然遇到同样的错误! 在回答问题后修改问题不是很有帮助。你仍然没有关闭连接。 我应该最后关闭块中的连接吗? @salma。我不得不赞扬你试图解决这个问题。很多时候,客户只是简单地将 open_cursors 参数作为“修复”。我相信这个小组中的聪明人会找到你问题的根源。 【参考方案1】:

“我不知道为什么会出现这个错误”

会不会是这个错别字?

            if (ps2 != null)
                try 
                    ps.close();
                 catch (Exception exx) 
                

您正在关闭 ps 而不是 ps2

【讨论】:

APC,我修改了它,但我仍然遇到同样的错误! 函数 fichierIndius2.ecrireDossier(dos);和 fichierIndius.ecrireDossier(dos); ?他们与 db 有关系吗?如果是,您可以发布代码吗? 还有cnnOracle.getConnexion().,它有什么作用? 它有一个连接,它是在另一个项目中定义的一个类。【参考方案2】:

您正在(或曾经)在 else 中将 rsps 设置为 null,即当 rc.getInt(1) == 0 时。这意味着当你到达 finally 块时,这些测试会失败,psrs 无法关闭:

            if (rs != null)
                try 
                    rs.close();
                 catch (Exception exx) 
                
            ....
            if (ps != null)
                try 
                    ps.close();
                 catch (Exception exx) 
                

正如@APC 已经指出的那样,您也(或曾经)在这里关闭了错误的陈述:

            if (ps2 != null)
                try 
                    ps.close();
                 catch (Exception exx) 
                

更大的问题是您没有像您声称的那样释放您的连接。有对cnnOracle.fermerConnexion() 的调用,但在异常处理程序中:

...
         catch (Exception ex) 
            requete.fermer();

            fichierIndius.fermerSansException();
            fichierIndius2.fermerSansException();
            cnnAS400.fermerConnexion();
            cnnAS400FO.fermerConnexion();
            cnnOracle.fermerConnexion();
            System.err
                    .println("Erreur d'écriture dans le fichier d'indus! /        EXC : "
                            + ex);
            return;
        
        finally
...

在您(正确)关闭语句和结果集之后,您还需要关闭 finally 块中的连接。

您还需要查看cnnOracle.fermerConnexion() 在做什么。你打电话给cnnOracle.getConnexion() 两次,每次你准备好的陈述一次。如果这些返回不同 连接,并且fermerConnexion() 只关闭一个,那么你也在那里泄漏。您需要调查它们内部发生的情况。

使用一个连接会更正常,因此您有一个名为conn 的变量,您使用cnnOracle.getConnexion() 设置它,然后将您准备好的语句创建为ps = conn.prepareStatement(...)

您目前似乎正在获取连接并在循环内重新创建和销毁准备好的语句。在循环之前获取连接并准备语句一次,然后在循环内执行它们会更有效。然后在循环完成后关闭准备好的语句和连接(并且仍然在异常处理程序中,因为它返回给调用者,并且 try 块的 finally 块将不再关闭它们)。

【讨论】:

非常感谢 Alex 的回复,我尝试按照您在我的代码中提到的内容进行操作,但现在我收到错误消息:java.lang.NullPointerException。 我只是忘记用 null 实例化准备好的语句。现在它起作用了。非常感谢!

以上是关于错误 ORA-01000: 超出最大打开游标的主要内容,如果未能解决你的问题,请参考以下文章

错误 ORA-01000: 超出最大打开游标

ORA-01000: 超出最大打开游标 - java 代码失败

jdbc 查询5万条数据出现 ORA-00604: 递归 SQL 级别 1 出现错误 ORA-01000: 超出打开游标的最大数

Doctrine + Oracle = 超出最大打开游标 (ORA-01000)

使用 Oracle 的 Spring Boot 应用程序 - ORA-01000:超出最大打开游标 - 负载测试期间发生错误

java.sql.SQLException: ORA-01000: 超出打开游标的最大数