java.sql.SQLException: - ORA-01000: máximo de cursores abertos excedido

115

Estou recebendo uma exceção ORA-01000 SQL. Portanto, tenho algumas dúvidas relacionadas a isso.

  1. Os cursores máximos abertos estão exatamente relacionados ao número de conexões JDBC ou também aos objetos de instrução e conjunto de resultados que criamos para uma única conexão? (Estamos usando pool de conexões)
  2. Existe uma maneira de configurar o número de objetos de instrução / conjunto de resultados no banco de dados (como conexões)?
  3. É aconselhável usar a instrução de variável de instância / objeto de conjunto de resultados em vez de instrução local de método / objeto de conjunto de resultados em um único ambiente de thread?
  4. A execução de uma instrução preparada em um loop causa esse problema? (Claro, eu poderia ter usado sqlBatch) Observação: pStmt é fechado quando o loop termina.

    { //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 
    
  5. O que acontecerá se conn.createStatement () e conn.prepareStatement (sql) forem chamados várias vezes em um único objeto de conexão?

Edit1: 6. O uso do objeto de instrução de referência Weak / Soft ajudará na prevenção do vazamento?

Edit2: 1. Existe alguma maneira, eu posso encontrar todos os "statement.close ()" s ausentes no meu projeto? Eu entendo que não é um vazamento de memória. Mas eu preciso encontrar uma referência de instrução (onde close () não é executado) elegível para coleta de lixo? Alguma ferramenta disponível? Ou tenho que analisá-lo manualmente?

Por favor me ajude a entender isso.

Solução

Para encontrar o cursor aberto no banco de dados Oracle para o nome de usuário -VELU

Vá para a máquina ORACLE e inicie o sqlplus como sysdba.

[oracle@db01 ~]$ sqlplus / as sysdba 

Então corra

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';

Se possível, leia minha resposta para entender melhor minha solução

Kanagavelu Sugumar
fonte
Você pode postar seu código completo? Seria interessante ver onde você está fechando as chaves de abertura abertas parafor (String language : additionalLangs) {
Jåcob
@ Kanagavelu Sugumar: por que não fazer 5 perguntas diferentes no SO?
Jayan,
1
Aqui está uma resposta que achei muito útil: stackoverflow.com/a/4507507/501113
chaotic3quilibrium
Verifique se a resposta é útil: stackoverflow.com/questions/34716456/…
Manu
Para rastrear cursores abertos no Oracle, você também pode dar uma olhada na SYS.V$OPEN_CURSORvisualização. Isso fornecerá não apenas o SID, mas também o texto SQL.
Bass

Respostas:

290

ORA-01000, o erro máximo de cursores abertos, é um erro extremamente comum no desenvolvimento de banco de dados Oracle. No contexto do Java, isso acontece quando o aplicativo tenta abrir mais ResultSets do que cursores configurados em uma instância de banco de dados.

As causas comuns são:

  1. Erro de configuração

    • Você tem mais threads em seu aplicativo consultando o banco de dados do que cursores no banco de dados. Um caso é quando você tem uma conexão e um pool de threads maior que o número de cursores no banco de dados.
    • Você tem muitos desenvolvedores ou aplicativos conectados à mesma instância de banco de dados (que provavelmente incluirá muitos esquemas) e juntos estão usando muitas conexões.
    • Solução:

  2. Vazamento do cursor

    • Os aplicativos não estão fechando ResultSets (em JDBC) ou cursores (em procedimentos armazenados no banco de dados)
    • Solução : Os vazamentos do cursor são bugs; aumentar o número de cursores no banco de dados simplesmente atrasa a falha inevitável. Vazamentos podem ser encontrados usando análise de código estático , JDBC ou registro em nível de aplicativo e monitoramento de banco de dados .

fundo

Esta seção descreve parte da teoria por trás dos cursores e como o JDBC deve ser usado. Se você não precisa saber o plano de fundo, pode pular isso e ir direto para 'Eliminar vazamentos'.

O que é um cursor?

Um cursor é um recurso no banco de dados que mantém o estado de uma consulta, especificamente a posição em que um leitor está em um ResultSet. Cada instrução SELECT tem um cursor, e os procedimentos armazenados PL / SQL podem abrir e usar quantos cursores forem necessários. Você pode descobrir mais sobre cursores no Orafaq .

Uma instância de banco de dados normalmente atende a vários esquemas diferentes , muitos usuários diferentes, cada um com várias sessões . Para fazer isso, ele possui um número fixo de cursores disponíveis para todos os esquemas, usuários e sessões. Quando todos os cursores estão abertos (em uso) e chega uma solicitação que exige um novo cursor, a solicitação falha com um erro ORA-010000.

Encontrar e definir o número de cursores

O número é normalmente configurado pelo DBA na instalação. O número de cursores atualmente em uso, o número máximo e a configuração podem ser acessados ​​nas funções do Administrador no Oracle SQL Developer . No SQL, ele pode ser definido com:

ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;

Relacionando JDBC na JVM a cursores no banco de dados

Os objetos JDBC abaixo são fortemente acoplados aos seguintes conceitos de banco de dados:

  • A Conexão JDBC é a representação do cliente de uma sessão de banco de dados e fornece transações de banco de dados . Uma conexão pode ter apenas uma única transação aberta a qualquer momento (mas as transações podem ser aninhadas)
  • Um ResultSet JDBC é suportado por um único cursor no banco de dados. Quando close () é chamado no ResultSet, o cursor é liberado.
  • Um JDBC CallableStatement invoca um procedimento armazenado no banco de dados, geralmente escrito em PL / SQL. O procedimento armazenado pode criar zero ou mais cursores e pode retornar um cursor como um ResultSet JDBC.

JDBC é thread-safe: é normal passar os vários objetos JDBC entre threads.

Por exemplo, você pode criar a conexão em um segmento; outro encadeamento pode usar essa conexão para criar um PreparedStatement e um terceiro encadeamento pode processar o conjunto de resultados. A única restrição principal é que você não pode ter mais de um ResultSet aberto em um único PreparedStatement a qualquer momento. Consulte O banco de dados Oracle oferece suporte a várias operações (paralelas) por conexão?

Observe que uma confirmação de banco de dados ocorre em uma conexão e, portanto, todos os DML (INSERT, UPDATE e DELETE) nessa conexão serão confirmados juntos. Portanto, se você deseja oferecer suporte a várias transações ao mesmo tempo, deve ter pelo menos uma conexão para cada transação simultânea.

Fechando objetos JDBC

Um exemplo típico de execução de ResultSet é:

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) { }
}

Observe como a cláusula finally ignora qualquer exceção gerada pelo close ():

  • Se você simplesmente fechar o ResultSet sem tentar {} catch {}, ele pode falhar e impedir que a instrução seja fechada
  • Queremos permitir que qualquer exceção levantada no corpo da tentativa se propague para o chamador. Se você tiver um loop, por exemplo, criando e executando instruções, lembre-se de fechar cada instrução dentro do loop.

No Java 7, a Oracle introduziu a interface AutoCloseable que substitui a maior parte do padrão Java 6 por alguns bons açúcares sintáticos.

Segurando objetos JDBC

Os objetos JDBC podem ser mantidos com segurança em variáveis ​​locais, instância de objeto e membros de classe. Geralmente é uma prática melhor:

  • Use instância de objeto ou membros de classe para manter objetos JDBC que são reutilizados várias vezes por um período mais longo, como Connections e PreparedStatements
  • Use variáveis ​​locais para ResultSets, uma vez que elas são obtidas, executadas em loop e fechadas normalmente dentro do escopo de uma única função.

No entanto, há uma exceção: se você estiver usando EJBs ou um contêiner Servlet / JSP, deverá seguir um modelo de threading rígido:

  • Apenas o servidor de aplicativos cria threads (com os quais lida com as solicitações de entrada)
  • Apenas o Application Server cria conexões (que você obtém do pool de conexão)
  • Ao salvar valores (estado) entre chamadas, você deve ter muito cuidado. Nunca armazene valores em seus próprios caches ou membros estáticos - isso não é seguro em clusters e outras condições estranhas, e o servidor de aplicativos pode fazer coisas terríveis com seus dados. Em vez disso, use beans com estado ou um banco de dados.
  • Em particular, nunca mantenha objetos JDBC (Connections, ResultSets, PreparedStatements, etc) em diferentes invocações remotas - deixe o Application Server gerenciar isso. O Application Server não apenas fornece um pool de conexão, mas também armazena em cache seus PreparedStatements.

Eliminando vazamentos

Existem vários processos e ferramentas disponíveis para ajudar a detectar e eliminar vazamentos de JDBC:

  1. Durante o desenvolvimento - detectar bugs no início é de longe a melhor abordagem:

    1. Práticas de desenvolvimento: Boas práticas de desenvolvimento devem reduzir o número de bugs em seu software antes que ele deixe a mesa do desenvolvedor. As práticas específicas incluem:

      1. Programação em pares , para educar aqueles sem experiência suficiente
      2. Revisões de código porque muitos olhos são melhores do que um
      3. Teste de unidade, o que significa que você pode exercitar toda e qualquer base de código a partir de uma ferramenta de teste que torna a reprodução de vazamentos trivial
      4. Use bibliotecas existentes para pool de conexão ao invés de construir seu próprio
    2. Análise de código estático: Use uma ferramenta como o excelente Findbugs para realizar uma análise de código estático. Isso pega muitos lugares onde o close () não foi tratado corretamente. Findbugs tem um plug-in para Eclipse, mas também funciona de forma autônoma para eventos pontuais, tem integrações com Jenkins CI e outras ferramentas de construção

  2. Em tempo de execução:

    1. Capacidade de retenção e compromisso

      1. Se a capacidade de manutenção do ResultSet for ResultSet.CLOSE_CURSORS_OVER_COMMIT, o ResultSet será fechado quando o método Connection.commit () for chamado. Isso pode ser definido usando Connection.setHoldability () ou usando o método sobrecarregado Connection.createStatement ().
    2. Registrando em tempo de execução.

      1. Coloque boas instruções de log em seu código. Eles devem ser claros e compreensíveis para que o cliente, a equipe de suporte e os colegas de equipe possam entender sem treinamento. Eles devem ser concisos e incluir a impressão dos valores de estado / internos de variáveis ​​e atributos-chave para que você possa rastrear a lógica de processamento. Um bom registro é fundamental para depurar aplicativos, especialmente aqueles que foram implantados.
      2. Você pode adicionar um driver JDBC de depuração ao seu projeto (para depuração - não o implemente). Um exemplo (eu não usei) é log4jdbc . Em seguida, você precisa fazer uma análise simples neste arquivo para ver quais execuções não têm um fechamento correspondente. A contagem de aberturas e fechamentos deve destacar se há um problema potencial

        1. Monitorando o banco de dados. Monitore seu aplicativo em execução usando ferramentas como a função SQL Developer 'Monitor SQL' ou o Quest's TOAD . O monitoramento é descrito neste artigo . Durante o monitoramento, você consulta os cursores abertos (por exemplo, da tabela v $ sesstat) e revisa seu SQL. Se o número de cursores está aumentando e (o mais importante) tornando-se dominado por uma instrução SQL idêntica, você sabe que há um vazamento com esse SQL. Pesquise seu código e analise.

Outros pensamentos

Você pode usar WeakReferences para lidar com o fechamento de conexões?

Referências fracas e suaves são maneiras de permitir que você faça referência a um objeto de uma maneira que permita que a JVM colete o referente a qualquer momento que julgar adequado (assumindo que não haja cadeias de referência fortes para esse objeto).

Se você passar um ReferenceQueue no construtor para a referência suave ou fraca, o objeto é colocado no ReferenceQueue quando o objeto é GC'ed quando ocorre (se ocorrer). Com essa abordagem, você pode interagir com a finalização do objeto e pode fechar ou finalizar o objeto naquele momento.

As referências fantasmas são um pouco mais estranhas; seu propósito é apenas controlar a finalização, mas você nunca pode obter uma referência ao objeto original, então será difícil chamar o método close () nele.

No entanto, raramente é uma boa ideia tentar controlar quando o GC é executado (Weak, Soft e PhantomReferences permitem que você saiba após o fato de que o objeto está enfileirado para GC). Na verdade, se a quantidade de memória na JVM for grande (por exemplo, -Xmx2000m), você pode nunca fazer o GC no objeto e ainda terá o ORA-01000. Se a memória da JVM for pequena em relação aos requisitos do seu programa, você pode descobrir que os objetos ResultSet e PreparedStatement são submetidos ao GC imediatamente após a criação (antes que você possa ler a partir deles), o que provavelmente irá falhar seu programa.

TL; DR: O mecanismo de referência fraca não é uma boa maneira de gerenciar e fechar objetos Statement e ResultSet.

Andrew Alcock
fonte
3
Se você criar instruções em um loop, certifique-se de que ele esteja fechado no loop, caso contrário, você acabará fechando apenas a última instrução.
basiljames
Obrigado, basiljames. Acabei de editar a resposta para adicionar o ponto que você fez.
Andrew Alcock,
@ Andrew Alcock Muito obrigado! Andrew. Você poderia responder a 6ª também.
Kanagavelu Sugumar
@AndrewAlcock Por favor .. por favor .. por favor .. responda minha sétima pergunta também. Desde nosso projeto, estamos enfrentando ORA-01000 com muita frequência durante os testes de carga. Suas contribuições são mais valiosas para mim. Muito obrigado antecipadamente!
Kanagavelu Sugumar
RE: 7 - você pode tentar a pesquisa de proximidade usando uma ferramenta como grep. Ao reconhecer um SQL (selecionar, inserir, atualizar, excluir), veja a proximidade da palavra close () ao lado da instrução. Se a proximidade estiver mais longe do que o esperado, essa pode ser uma forma de investigar onde está faltando. lightboxtechnologies.com/2012/07/27/…
Dom
28

Estou adicionando mais alguns entendimentos.

  1. O cursor é apenas sobre um objeto de instrução; Não é resultSet nem o objeto de conexão.
  2. Mas ainda temos que fechar o conjunto de resultados para liberar alguma memória do oráculo. Mesmo assim, se você não fechar o conjunto de resultados, isso não será contado para os CURSORES.
  3. Fechar o objeto Statement também fechará automaticamente o objeto do conjunto de resultados.
  4. O cursor será criado para todas as instruções SELECT / INSERT / UPDATE / DELETE.
  5. Cada instância do ORACLE DB pode ser identificada usando o oracle SID; da mesma forma, o ORACLE DB pode identificar cada conexão usando o SID de conexão. Ambos os SID são diferentes.
  6. Portanto, a sessão do ORACLE nada mais é do que uma conexão jdbc (tcp); que nada mais é do que um SID.
  7. Se definirmos o máximo de cursores como 500, será apenas para uma sessão / conexão / SID JDBC.
  8. Portanto, podemos ter várias conexões JDBC com seu respectivo número de cursores (instruções).
  9. Depois que a JVM for encerrada, todas as conexões / cursores serão fechados, OU JDBCConnection for encerrada. CURSORS com relação a essa conexão será encerrada.

Loggin como sysdba.

Em Putty (login Oracle):

  [oracle@db01 ~]$ sqlplus / as sysdba

No SqlPlus:

Nome do usuário: sys as sysdba

Defina o valor de session_cached_cursors como 0 para que não feche os cursores.

 alter session set session_cached_cursors=0
 select * from V$PARAMETER where name='session_cached_cursors'

Selecione o conjunto de valus OPEN_CURSORS existente por conexão no banco de dados

 SELECT max(a.value) as highest_open_cur, p.value as max_open_cur FROM v$sesstat a, v$statname b, v$parameter p WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current' AND p.name= 'open_cursors'  GROUP BY p.value;

Abaixo está a consulta para localizar a lista de SID / conexões com os valores do cursor aberto.

 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 = 'SCHEMA_NAME_IN_CAPS'

Use a consulta abaixo para identificar os sql's nos cursores abertos

 SELECT oc.sql_text, s.sid 
 FROM v$open_cursor oc, v$session s
 WHERE OC.sid = S.sid
 AND s.sid=1604
 AND OC.USER_NAME ='SCHEMA_NAME_IN_CAPS'

Agora depure o código e aproveite !!! :)

Kanagavelu Sugumar
fonte
1
Aqui está outra consulta que parece funcionar bem: stackoverflow.com/a/2560415/32453
rogerdpack
4

Corrija o seu código assim:

try
{ //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
{ //finally starts
   pStmt.close()
} 

Tem certeza de que está realmente fechando suas declarações, conexões e resultados?

Para analisar objetos abertos, você pode implementar um padrão de delegador, que envolve o código em torno de seus objetos de estado, conexão e resultado. Então você verá se um objeto será fechado com sucesso.

Um exemplo para: pStmt = obj. getConnection () .prepareStatement (sql);

    class obj{ 

    public Connection getConnection(){
    return new ConnectionDelegator(...here create your connection object and put it into ...);

    } 
}


class ConnectionDelegator implements Connection{
    Connection delegates;

    public ConnectionDelegator(Connection con){
       this.delegates = con;
    }

    public Statement prepareStatement(String sql){
        return delegates.prepareStatement(sql);
    }

    public void close(){
        try{
           delegates.close();
        }finally{
           log.debug(delegates.toString() + " was closed");
        }
    }
}
Mirko
fonte
3

Se o seu aplicativo for um aplicativo Java EE em execução no Oracle WebLogic como servidor de aplicativos, uma possível causa para esse problema é a configuração de tamanho do cache de instrução no WebLogic.

Se a configuração de tamanho do cache de instrução para uma fonte de dados específica for quase igual ou maior que a configuração de contagem máxima de cursores abertos do banco de dados Oracle, todos os cursores abertos podem ser consumidos por instruções SQL em cache mantidas abertas pelo WebLogic, resultando no erro ORA-01000.

Para resolver isso, reduza a configuração de tamanho do cache de instrução para cada fonte de dados WebLogic que aponta para o banco de dados Oracle para ser significativamente menor do que a configuração de contagem máxima de cursor no banco de dados.

No WebLogic 10 Admin Console, a configuração de tamanho do cache de instrução para cada fonte de dados pode ser encontrada em Serviços (navegação à esquerda)> Fontes de dados> (fonte de dados individual)> guia Pool de conexão.

Jon Schneider
fonte
1
O Hibernate também possui um cache de instrução. Veja também developer.jboss.org/wiki/…
Pino
3

Eu também tinha enfrentado esse problema. A exceção abaixo costumava vir

java.sql.SQLException: - ORA-01000: maximum open cursors exceeded

Eu estava usando Spring Framework com Spring JDBC para camada dao.

Meu aplicativo costumava vazar cursores de alguma forma e, depois de alguns minutos ou mais, costumava me dar essa exceção.

Depois de muita depuração e análise minuciosas, descobri que havia o problema com a indexação, a chave primária e as restrições exclusivas em uma das tabelas que estavam sendo usadas na consulta que estava executando.

Meu aplicativo estava tentando atualizar as colunas que foram indexadas por engano . Portanto, sempre que meu aplicativo estava atingindo a consulta de atualização nas colunas indexadas, o banco de dados estava tentando fazer a reindexação com base nos valores atualizados. Estava vazando os cursores .

Consegui resolver o problema fazendo a indexação adequada nas colunas que foram usadas para pesquisar na consulta e aplicando as restrições apropriadas sempre que necessário.

Piyush Verma
fonte
2

Eu enfrentei o mesmo problema (ORA-01000) hoje. Tive um loop for na tentativa {}, para executar uma instrução SELECT em um banco de dados Oracle muitas vezes, (cada vez alterando um parâmetro) e, por fim, {} fiz meu código fechar Resultset, PreparedStatement e Connection como de costume . Mas assim que cheguei a uma quantidade específica de loops (1000), recebi o erro do Oracle sobre muitos cursores abertos.

Com base na postagem de Andrew Alcock acima, fiz alterações para que, dentro do loop, fechasse cada conjunto de resultados e cada instrução depois de obter os dados e antes de fazer o loop novamente, e isso resolveu o problema.

Além disso, o mesmo problema ocorreu em outro loop de Instruções Insert, em outro banco de dados Oracle (ORA-01000), desta vez após 300 instruções. Novamente, foi resolvido da mesma maneira, portanto, PreparedStatement ou ResultSet ou ambos contam como cursores abertos até que sejam fechados.

Kinnison84
fonte
Isso não parece certo. Spring documenta que é responsável por fechar ResultSets ( docs.spring.io/spring/docs/current/spring-framework-reference/… ).
Ryan
apenas para esclarecimento, nesses exemplos eu não estava usando o Spring.
Kinnison84
1

Você definiu autocommit = true? Se não, tente isto:

{ //method try starts  
    String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
    Connection conn = obj.getConnection()
    pStmt = conn.prepareStatement(sql);

    for (String language : additionalLangs) {
        pStmt.setLong(1, subscriberID);
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
        conn.commit();
    }
} //method/try ends { 
    //finally starts
    pStmt.close()
} //finally ends 
Paweloque
fonte
Você poderia responder às outras perguntas também?
Kanagavelu Sugumar
2
Autocommit não fecha conexões - apenas confirma automaticamente cada instrução imediatamente após a execução. Se você estiver usando o autocommit, não estará obtendo valor de uma das propriedades mais importantes do banco de dados - as transações. Você pode considerar o uso de um banco de dados NoSQL.
Andrew Alcock
1

consulta para encontrar sql que abriu.

SELECT s.machine, oc.user_name, oc.sql_text, count(1) 
FROM v$open_cursor oc, v$session s
WHERE oc.sid = s.sid
and S.USERNAME='XXXX'
GROUP BY user_name, sql_text, machine
HAVING COUNT(1) > 2
ORDER BY count(1) DESC
Hlex
fonte
1

Esse problema ocorre principalmente quando você está usando o pool de conexão, porque quando você fecha a conexão, essa conexão volta para o pool de conexão e todos os cursores associados a essa conexão nunca são fechados, pois a conexão com o banco de dados ainda está aberta. Portanto, uma alternativa é diminuir o tempo de conexão ociosa das conexões no pool, de modo que, sempre que a conexão ficar ociosa por, digamos, 10 segundos, a conexão com o banco de dados será fechada e uma nova conexão criada para colocar no pool.

Raveesh Badoni
fonte
0

Em nosso caso, estávamos usando o Hibernate e tínhamos muitas variáveis ​​referenciando a mesma entidade mapeada do Hibernate. Estávamos criando e salvando essas referências em um loop. Cada referência abria um cursor e o mantinha aberto.

Descobrimos isso usando uma consulta para verificar o número de cursores abertos durante a execução de nosso código, avançando com um depurador e comentando seletivamente as coisas.

Quanto ao motivo de cada nova referência abrir outro cursor - a entidade em questão tinha coleções de outras entidades mapeadas para ela e acho que isso tinha algo a ver com isso (talvez não apenas isso, mas em combinação com a forma como configuramos o modo de busca e Configurações de cache). O próprio Hibernate teve erros relacionados à falha ao fechar os cursores abertos, embora pareça que eles foram corrigidos em versões posteriores.

Como não precisávamos ter tantas referências duplicadas para a mesma entidade de qualquer maneira, a solução foi parar de criar e manter todas essas referências redundantes. Uma vez que fizemos isso, o problema era quando estávamos longe.

dshiga
fonte
0

Tive esse problema com minha fonte de dados em WildFly e Tomcat, conectando a um Oracle 10g.

Descobri que, sob certas condições, a instrução não foi fechada, mesmo quando a instrução.close () foi chamada. O problema era com o driver Oracle que estávamos usando: ojdbc7.jar. Este driver é destinado ao Oracle 12c e 11g, e parece que tem alguns problemas quando é usado com o Oracle 10g, então eu fiz downgrade para ojdbc5.jar e agora tudo está funcionando bem.

Gilbertoag
fonte
0

Eu enfrentei o mesmo problema porque estava consultando o banco de dados por mais de 1000 iterações. Eu usei try e finalmente no meu código. Mas ainda estava recebendo erro.

Para resolver isso eu apenas loguei no oracle db e executei a consulta abaixo:

ALTER SYSTEM SET open_cursors = 8000 SCOPE = BOTH;

E isso resolveu meu problema imediatamente.

RArora
fonte
Isso salvou alguns sintomas, mas não resolveu o problema. Você precisa corrigir seu código para que ele feche os cursores assim que terminar de usá-los.
APC