Erro Cursores Oracle

19 respostas
S

Bom dia!!!

Estou tendo o seguinte erro

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

Estou fechando todos os ResultSet e PreparedStatement que estou usando e fecho a conexao no final do aplicativo mas mesmo assinesta acontecendo esse erro.

Alguem tem alguma sugestao?

Valeu

19 Respostas

A

Em algum lugar está faltando fechar o preparedStateament.

Você está dentro de um LOOP ?
Se estiver procure fechar a cada implementação do loop.

Exemplo

while ((linha_file = buffer_file.readLine()) != null) {
                    j++;
                    campos = linha_file.split(";");

                    pstmt = conn.prepareStatement(sql.toString());
                    pstmt.setString(1, ano + mes); 
                    pstmt.setString(2, campos[3]);
                    pstmt.execute();
                    if (pstmt != null) {
                        pstmt.close();
                    }
            }
S

Estou fechando todos os PreparedStatement e ResultSet, estou fazendo um loop e chamando esses metodos mas os metodos q usso estao fexando fexando oPreparedStatement e ResultSet sem erro quando fecho a conexao e abro dentro do codigo a daca 200 registro processados de novo tudo funciona normal alguem tem outra solução?

Valeu

A

Deve haver algum que não está sendo fechado. Vale verificar novamente.
Pois o problema é que ele está abrindo vários cursores e não está fechando.

S

Fiz um debug passo a passo e nao chaei nada mas vou verificar de novo.

Estou usando este comando do oracle

select o.sid, osuser, machine, count(*) num_curs from v$open_cursor o, v$session s where o.sid=s.sid group by o.sid, osuser, machine order by num_curs;
para verificar a quantidade de cursores q tenho aberto e este

select q.sql_text, count(*) from v$open_cursor o, v$sql q where q.hash_value=o.hash_value and o.sid IN (<sid>) group by q.sql_text order by 2;

para verificar quais os sql q estao abertos em casa cursos mas nao ha nada do meu programa apenas do oracle mesmo.

Vc sabe se q auntidade de cursos e dividida para cada usuario ou se e uma quantidade pra cada?
EX: sao 500 cursores por exemplo esses cursores sao divididos entre todos os usuarios ou se sao 500 so pra mim.

Valeu

A

A quantida de cursores é Global, ou seja é compartilhada entre todos os usuários do Oracle.

S

OK,
Obrigado amigo pela ajuda vou ver oq faço aqui.

Valeu

F

estou com o mesmo problema.

Eu fecho os statments e resultset e libero as conexões pro pool. O problema que reparei é que ao fechar os Statments e resultsets seria para liberar os cursores, porem os cursores só são liberados quando a conexão é fechada.

Não há a menor possibilidade de fechar as conexões, pois de que adianta fechar uma para devolve-la ao pool? o pool teria que criar outra conexao e acaba perdendo o sentido utiliza-lo. (não sei por que diabos o pool do sistema foi criado na raça!)

Reparei que nos ResultsSets tem um método que é setHoldability. Neste método eu passo a constante CLOSE_CURSORS_AT_COMMIT mas ele não fecha os cursores de maneira nenhuma.

Não sei se é alguma limitação do driver jdbc, já entrei no site da oracle e baixei o ultimo e não mudou nada.

por enquanto, pra contornar a situação eu estou utilizando uma gambi, que quando lança uma SQLException e a mensagem é de maximo de cursores eu fecho a conexao, abro outra, executo o comando novamente e devolvo a conexao ao pool, porem isso é temporario mesmo, para ter como testar o sistema até encontar uma solução.

Se encontar a solução por favor poste, estou pesquisando e farei o mesmo.

Abraço

J

Esse problema pode existir por conta do drive que esta sendo usado. Procure usar o drive disponibilizado pela oracle. Outra coisa que vc pode fazer é rodar o programa com a seguinte modificação: deixar os cursores serem abertos e fechar imediatamente após a utilização dos mesmo. Assim vc isola o problema e se estourar novamente vc sabera que o problema não está nos statements que vc está criando. Outra forma de encontrar o problema é tentar debugar, crie um plano de debug tenha lapis e papel na mão e muita paciência, mas um dia vc descobre.

Sempre que tive esse problema foi problema humano mesmo. Veja se vc não está levantando alguma execeção e deixando o cursos aberto, algum condicional que leve a execução para alguma linha que não fecha o cursor, enfim, continue procurando q vc acha.

F

Acredito que o problema não é fechar os Statments, pois até nas consultas feitas pelo DataProvider ocorre o problema, e o Statment é fechado. O que sobrou agora é o driver do oracle… porem eu baixei o mais recente hoje e continuo com o problema.

A unica coisa que realmente fecha os cursores é fechar a conexão…

falou

A

Só corrigindo o que o amigo Ferryman citou, dizendo que é preciso fechar a conexão pra liberar o cursor, isso não é verdade, só de você fechar o steatment ele já libera o cursos vide exemplo que postei.
o que pode estar acontecendo é o pool de conexões estar demorando pra liberar o cursor, no meu caso como implementei a conexão “na mão” só de eu fechar o steatment já consegui resolver o problema.

J

O comando que garante o fechamento do cursor é

ResultSet rset = ps.executeQuery();
...
...

[b]rset.getStatement().close();[/b]
rset.close();
A

E no meu caso como eu só estava usando um PrepareSteatment pra dar um insert, era só necessário fechar o steatment

if(pstmt != null){
   pstmt.close();
}
F

Sinceramente não faço idéia do que está acontecendo aqui, pois o pool de conexões foi implementado na mão, e a conexão é realmente fechada quando se chama o método close().
Mesmo fechando o statment e o resultset, os cursores não estão sendo fechados. Só quando a conexão é fechada.

Valeu pela ajuda pessoal

J

Se você usa Tomcat dê uma olhada nesses parâmetros do xml de sua aplicação:

removeAbandoned true removeAbandonedTimeout 300
F

Não uso o tomCat não… o pool de conexões foi implementado na mão aqui (não me pergunte porque).

P

Faz assim…

Roda o sistema e fiscaliza a quantidade de cursores que estão sendo abertos com essa query:

/* SELECIONA TODOS OS OPEN CURSORS DE CADA MAQUINA */
SELECT v.value as numopencursors ,s.machine ,s.osuser,s.username
FROM V$SESSTAT v, V$SESSION s
WHERE v.statistic# = 3 and v.sid = s.sid

Procure fizar atualizando a consulta e ver se a quantidade de cursores so aumenta, se for isso, logo apos o erro vc pode verificar qual SELECT que esta te sacaneando com essa query aki:

/* SELECIONA DADOS DE CADA OPEN CURSOR */
select user_name, status, osuser, machine, a.sql_text, c.sql_text
from v$session b, v$open_cursor a, V$SQLAREA c
where a.sid = b.sid
and c.address = a.address

Abraço !!!

Aff… so agora que vi que esse post eh antigo.
=/

Kraca… ja é o segundo que desenterro hoje… ^^

R

Ferryman:
estou com o mesmo problema.

Eu fecho os statments e resultset e libero as conexões pro pool. O problema que reparei é que ao fechar os Statments e resultsets seria para liberar os cursores, porem os cursores só são liberados quando a conexão é fechada.

Não há a menor possibilidade de fechar as conexões, pois de que adianta fechar uma para devolve-la ao pool? o pool teria que criar outra conexao e acaba perdendo o sentido utiliza-lo. (não sei por que diabos o pool do sistema foi criado na raça!)

Reparei que nos ResultsSets tem um método que é setHoldability. Neste método eu passo a constante CLOSE_CURSORS_AT_COMMIT mas ele não fecha os cursores de maneira nenhuma.

Não sei se é alguma limitação do driver jdbc, já entrei no site da oracle e baixei o ultimo e não mudou nada.

por enquanto, pra contornar a situação eu estou utilizando uma gambi, que quando lança uma SQLException e a mensagem é de maximo de cursores eu fecho a conexao, abro outra, executo o comando novamente e devolvo a conexao ao pool, porem isso é temporario mesmo, para ter como testar o sistema até encontar uma solução.

Se encontar a solução por favor poste, estou pesquisando e farei o mesmo.

Abraço

Já que o tópico foi renascido, então vou fazer mais um comentário… afinal, ele não foi resolvido.

Estou utilizando controle de pool connections DBPool.
Também estou com o problema de fechar corretamente os ResultSet e Statements, mas os mesmo não são liberados imediatamente pelo DBPool, com isso quando realizo novas operações frequentemente ele estoura a exception de limite de cursores porque os mesmos ainda não foram liberados.

de acordo com os releases do componente (http://www.snaq.net/java/DBPool/) isso me parece um bug do DBPool na versão que estou usando.

Irei atualiza-lo para quer se o problema resolve.

R

Rafael_rst:
Ferryman:
estou com o mesmo problema.

Eu fecho os statments e resultset e libero as conexões pro pool. O problema que reparei é que ao fechar os Statments e resultsets seria para liberar os cursores, porem os cursores só são liberados quando a conexão é fechada.

Não há a menor possibilidade de fechar as conexões, pois de que adianta fechar uma para devolve-la ao pool? o pool teria que criar outra conexao e acaba perdendo o sentido utiliza-lo. (não sei por que diabos o pool do sistema foi criado na raça!)

Reparei que nos ResultsSets tem um método que é setHoldability. Neste método eu passo a constante CLOSE_CURSORS_AT_COMMIT mas ele não fecha os cursores de maneira nenhuma.

Não sei se é alguma limitação do driver jdbc, já entrei no site da oracle e baixei o ultimo e não mudou nada.

por enquanto, pra contornar a situação eu estou utilizando uma gambi, que quando lança uma SQLException e a mensagem é de maximo de cursores eu fecho a conexao, abro outra, executo o comando novamente e devolvo a conexao ao pool, porem isso é temporario mesmo, para ter como testar o sistema até encontar uma solução.

Se encontar a solução por favor poste, estou pesquisando e farei o mesmo.

Abraço

Já que o tópico foi renascido, então vou fazer mais um comentário… afinal, ele não foi resolvido.

Estou utilizando controle de pool connections DBPool.
Também estou com o problema de fechar corretamente os ResultSet e Statements, mas os mesmo não são liberados imediatamente pelo DBPool, com isso quando realizo novas operações frequentemente ele estoura a exception de limite de cursores porque os mesmos ainda não foram liberados.

de acordo com os releases do componente (http://www.snaq.net/java/DBPool/) isso me parece um bug do DBPool na versão que estou usando.

Irei atualiza-lo para quer se o problema resolve.

O DBPool faz cashing de Statement também, então eles não são liberados instantaneamente na hora que damos um “st.close();” o pool connections que controla quando irá encerrar efetivamente.

Com isso, resolvi meu problema desabilitando o cashing dos statement:

connectionPool.setCaching(false);
V

No meu caso este procedimento resolveu o problema:
abrir um cursor grande
e para cada ocorrencia fazer um outro select no banco

valeu!!

julianostr:
O comando que garante o fechamento do cursor é
ResultSet rset = ps.executeQuery();
...
...

[b]rset.getStatement().close();[/b]
rset.close();
Criado 25 de outubro de 2006
Ultima resposta 8 de abr. de 2010
Respostas 19
Participantes 8