当前位置: 首页 > 知识库问答 >
问题:

java.sql.sqlexception:-ora-01000:超过最大打开游标

贺波
2023-03-14

我得到一个ORA-01000 SQL异常。所以我有一些与之相关的疑问。

{ //method try starts  
  String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
  pStmt = obj.getConnection().prepareStatement(sql);
  pStmt.setLong(1, subscriberID);
  for (String language : additionalLangs) {
    pStmt.setInt(2, Integer.parseInt(language));
    pStmt.execute();
  }
} //method/try ends

{ //finally starts
   pStmt.close()
} //finally ends 

编辑1:6。使用弱/软引用语句对象是否有助于防止泄漏?

编辑2:1。有没有办法,我可以找到我的项目中所有缺失的“statement.close()”?我知道这不是内存泄漏。但是我需要找到一个符合垃圾收集条件的语句引用(在那里没有执行close())?有工具吗?还是我必须手动分析?

请帮我理解一下。

[oracle@db01 ~]$ sqlplus / as sysdba 
SELECT   A.VALUE,
    S.USERNAME,
    S.SID,
    S.SERIAL#
  FROM V$SESSTAT A,
    V$STATNAME B,
    V$SESSION S
  WHERE A.STATISTIC# = B.STATISTIC#
    AND S.SID        = A.SID
    AND B.NAME       = 'opened cursors current'
    AND USERNAME     = 'VELU';

共有1个答案

芮安顺
2023-03-14

ORA-01000是Oracle数据库开发中极为常见的错误。在Java上下文中,当应用程序试图打开的结果集多于数据库实例上配置的游标时,就会发生这种情况。

常见的原因有:

>

  • 配置错误

      null

    光标泄漏

    • 应用程序没有关闭ResultSets(在JDBC中)或游标(在数据库的存储过程中)
    • 解决方案:游标泄漏是bug;增加DB上的游标数量只是延迟了不可避免的失败。可以使用静态代码分析、JDBC或应用程序级日志记录以及数据库监视来发现泄漏。

    本节描述了游标背后的一些理论以及应该如何使用JDBC。如果你不需要了解背景,你可以跳过这个,直接进入‘消除漏洞’。

    游标是数据库上保存查询状态的资源,特别是读取器在结果集中的位置。每个SELECT语句都有一个游标,PL/SQL存储过程可以根据需要打开和使用任意数量的游标。您可以在Orafaq上找到更多关于游标的信息。

    一个数据库实例通常服务于几个不同的模式,许多不同的用户,每个用户都有多个会话。为此,它有固定数量的游标可用于所有模式、用户和会话。当所有游标都打开(正在使用中)并且请求需要新游标时,请求失败并出现ORA-010000错误。

    该号码通常由DBA在安装时配置。可以在Oracle SQL Developer的Administrator函数中访问当前使用的游标数、最大游标数和配置。在SQL中,可以通过以下方式设置:

    ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;
    
    • JDBC连接是数据库会话的客户端表示,并提供数据库事务。连接在任何时候只能打开一个事务(但事务可以嵌套)
    • 数据库上的单个游标支持JDBC结果集。当对ResultSet调用close()时,将释放游标。
    • JDBC CallableStatement调用数据库上的存储过程,通常用PL/SQL编写。存储过程可以创建零个或多个游标,并可以将游标作为JDBC结果集返回。

    JDBC是线程安全的:可以在线程之间传递各种JDBC对象。

    例如,您可以在一个线程中创建连接;另一个线程可以使用此连接创建PreparedStatement,第三个线程可以处理结果集。唯一的主要限制是,任何时候都不能对单个PreparedStatement打开多个ResultSet。请参见Oracle DB是否支持每个连接的多个(并行)操作?

    Statement stmt = conn.createStatement();
    try {
        ResultSet rs = stmt.executeQuery( "SELECT FULL_NAME FROM EMP" );
        try {
            while ( rs.next() ) {
                System.out.println( "Name: " + rs.getString("FULL_NAME") );
            }
        } finally {
            try { rs.close(); } catch (Exception ignore) { }
        }
    } finally {
        try { stmt.close(); } catch (Exception ignore) { }
    }
    

    注意finally子句如何忽略close()引发的任何异常:

    • 如果只关闭ResultSet,而不执行try{}catch{},则可能会失败并阻止关闭语句
    • 我们希望允许在try主体中引发的任何异常传播给调用方。如果您有一个循环,例如创建和执行语句,请记住关闭循环中的每个语句。

    在Java7中,Oracle引入了AutoCloseable接口,它用一些很好的语法糖取代了Java6的大部分样板。

    • 使用对象实例或类成员来保存在较长时间内多次重用的JDBC对象,如Connections和PreparedStatement
    • 对ResultSets使用局部变量,因为这些变量通常是在单个函数的作用域内获得、循环然后关闭的。

    但是,有一个例外:如果您使用EJB或Servlet/JSP容器,则必须遵循严格的线程模型:

    • 只有应用程序服务器创建线程(用于处理传入请求)
    • 只有应用程序服务器创建连接(从连接池中获得)
    • 在调用之间保存值(状态)时,必须非常小心。永远不要将值存储在您自己的缓存或静态成员中--这在跨集群和其他怪异的情况下是不安全的,应用服务器可能会对您的数据做可怕的事情。而是使用有状态bean或数据库。
    • 特别是,千万不要在不同的远程调用上持有JDBC对象(Connections、ResultSets、PreparedStatements等)--让应用程序服务器来管理这一点。应用程序服务器不仅提供连接池,还缓存PreparedStatements。

    有许多过程和工具可用于帮助检测和消除JDBC泄漏:

    >

  • 在开发期间-早期捕捉bug是最好的方法:

    >

  • 开发实践:好的开发实践应该在软件离开开发人员的办公桌之前减少软件中的bug数量。具体做法包括:

      null

    运行时:

    >

  • 可持有性和提交

    1. 如果ResultSet的可保持性为ResultSet.Close_Cursors_Over_Commit,则在调用Connection.Commit()方法时关闭ResultSet。这可以使用connection.setHoldability()或使用重载的connection.createStatement()方法进行设置。

    弱引用和软引用是允许您以允许JVM在它认为合适的任何时间垃圾收集引用的方式引用对象的方法(假设没有指向该对象的强引用链)。

    如果您将构造函数中的ReferenceQueue传递给软引用或弱引用,则当对象发生时(如果它发生了)被GC'ed时,该对象将被放置在ReferenceQueue中。使用这种方法,您可以与对象的完成交互,并且您可以在此时关闭或完成对象。

    幻象引用有点奇怪;它们的目的只是控制终结,但您永远无法获得对原始对象的引用,因此很难对其调用close()方法。

    但是,尝试控制运行GC的时间并不是一个好主意(弱、软和PhantomReferences在对象为GC排队之后会让您知道)。事实上,如果JVM中的内存量很大(例如-XMX2000M),您可能永远不会GC对象,您仍然会体验到ORA-01000。如果JVM内存相对于程序的要求较小,您可能会发现ResultSet和PreparedStatement对象在创建后(在您可以读取它们之前)立即被GCed,这可能会使程序失败。

    弱引用机制不是管理和关闭Statement和ResultSet对象的好方法。

  •  类似资料:
    • 问题内容: 我收到了ORA-01000 SQL异常。因此,我对此有一些疑问。 最大打开游标是否与JDBC连接的数量完全相关,还是与我们为单个连接创建的语句和结果集对象相关?(我们正在使用连接池) 有没有一种方法可以配置数据库中的语句/结果集对象的数量(如连接)? 是否建议在单线程环境中使用实例变量statement / resultset对象而不是方法local statement / resul

    • 在Eclipse中,我遇到了这个错误:*错误ORA-01000:超过了最大打开游标数,我已经在块中关闭了连接,但我不知道为什么会出现这个错误,这是我的JAVA代码。请帮帮我!

    • 我已经连接了Oracle数据库。现在我要面对 我使用代码插入数据: 它只适用于前500条记录,然后我有错误Ora-1000。我总共有大约6000条记录。我发现一些主题说应该改变配置,但我不能改变配置。 有没有其他方法可以解决这个错误?

    • 我得到了ORA-0300:超出了最大打开游标数

    • 我们的应用程序连接到Oracle数据库,我们使用Spring提供的JDBCTemboard与数据库交互。根据Spring JDBCTemboard的留档,它确保它将关闭所有连接和游标。但显然我们得到了以下打开游标的异常。 ORA-01000:组织上超过了最大打开游标数。springframework。jdbc。支持AbstractFallbackSQLExceptionTranslator。在or

    • 嘿,我正在使用Glassfish开源v4,我遇到了一个奇怪的问题。 我在管理控制台中定义了到Oracle 11g的JDBC连接池,并设置了: 初始和最小池大小:500 最大游泳池大小:1000 池大小调整数量::750 我已经为这个连接池创建了一个特定的用户。然而,有时当我检查数据库中打开的连接时,我发现有1000多个连接(我看到的最大连接数是1440个) 当发生这种情况时,任何查询尝试都会失败,