Hibernate+MySQL banco rejeitando conexão depois de algumas horas de funcionamento

8 respostas
ativa

Bom dia galera!

desenvolvi um software utilizando hibernate+MySQL. Este software fica ligado e funciona como um servidor, nao deve ser fechado e deve estar sempre em execução.
O grande problema é que depois de algumas horas de funcionamento, aprox 12hs ±, o banco ou hibernate, nao sei bem dizer, passa a rejeitar conexoes com o banco. aí se eu fechar o software e abrir denovo, o software volta a operar normalmente.

Nas minhas classes DAO, estou utilizando annotation, tenho um método que cria a conexao e transaçao, o método com a pesquisa que eu faço e um método para commit e fechar a conexao.
quando faço uma pesquisa chamo o método que cria a conexao e transaçao, depois chamo o metodo que faz a pesquisa e depois chamo o método que faz o commit e close da sessao.

estou utilizando hibernate e c3p0

O que pode ser?
alguem pode me ajudar?

normalmente recebo a mensagem de erro:

  • Cannot Open connection
  • Cannot load entity

OBRIGADO!

8 Respostas

yorgan

Você está utilizando um Singleton para instanciar o EntityManagerFactory?
Se estiver, provavelmente em algum momento o seu servidor está perdendo a conexão com o banco de dados e como a factory já foi instanciada, ela perde a conexão e não recupera. Mas quando você reinicia o servidor a factory abre uma nova conexão e por isso volta a funcionar.
Você tem que colocar um parametro no seu C3P0 para ele reconectar automaticamente.
Ou deixar o seu servidor de aplicação ou container servlet gerenciar isso para você.
Acredito que a segunda opção seja a mais recomendada.

Se ainda tiver dúvidas, poste o seu persistence.xml, a classe que instancia a factory e também seu DAO.

[]´s
Daniel

R

Dê uma olhada no blog da Caelum sobre Broken Pipe.
Talvez seja o seu problema. Para confirmar, olhe atentamente para a stack trace da sua aplicação.
http://blog.caelum.com.br/2009/10/19/a-java-net-socketexception-broken-pipe/

ativa

yorgan, nao entendi mto bem o q vc quis me dizer.
Se puder dar exemplos por gentileza.

Mas segue meu cfg.xml, minha classe hibernate util e minha classe dao.

hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- configuration pool via c3p0--> 
        <property name="c3p0.acquire_increment">15</property> 
        <property name="c3p0.idle_test_period">180</property> <!-- seconds --> 
        <property name="c3p0.max_size">3000</property> 
        <property name="c3p0.max_statements">0</property> 
        <property name="c3p0.min_size">10</property> 
        <property name="c3p0.timeout">300</property> <!-- seconds --> 
        <!-- DEPRECATED very expensive property name="c3p0.validate>--> 
        
        <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
        <property name="hibernate.connection.password">yyy</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/xyz</property>
        <property name="hibernate.connection.username">yyy</property>
        <property name="hibernate.default_schema">xyz</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.hbm2ddl.auto">validate</property>
        <property name="hibernate.connection.pool_size">1000</property>
        <mapping class="br.com.atv.vo.Equipamento"/>
        <mapping class="br.com.atv.vo.Tanques"/>
        <mapping class="br.com.atv.vo.Leitura"/>
        <mapping class="br.com.atv.vo.Email"/>
        <mapping class="br.com.atv.vo.Historico"/>
        <mapping class="br.com.atv.vo.Delivery"/>
        <mapping class="br.com.atv.vo.Alarmes"/>
        <mapping class="br.com.atv.vo.Conexoes"/>
    </session-factory>
</hibernate-configuration>
hibernateUtil.java
public class HibernateUtil {

    private static final SessionFactory sessionFactory;


    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
            // config file.
            sessionFactory = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void closeSession() {
        Session session = (Session) sessionFactory.getCurrentSession();
        //sessionFactory.set(null);

        if (session != null && session.isOpen()) {
            session.flush();
            session.close();
        }
    }
}
Método de busca de uma das DAO
public Equipamento findById(long l) {
        try 
        {
            Session session = HibernateUtil.getSessionFactory().openSession();
            Transaction transaction = session.beginTransaction();
            Equipamento instance = (Equipamento) session.get(Equipamento.class, l);
            transaction.commit();
            session.close();
            return instance;
        } catch (RuntimeException re) {
            throw re;
        }
    }

Baseado no meu código. consegue me ajudar ou dar exemplos com outro código?

Muito obrigado pela disposiçao em me ajudar.

Atenciosamente,
Thiago

yorgan

Como você pode ver na sua classe hibernateUtil, a SessionFactory só é instanciada na primeira requisição feita pelo DAO.
Então, se a conexão com o banco cair em algum momento que a aplicação estiver rodando, a factory não será instanciada novamente e a conexão não será reaberta.
No link que o riccaio passou existe uma explicação detalhada para o seu caso, mas para resumir, acho que trocando a linha:

<property name="c3p0.idle_test_period">180</property> <!-- seconds -->

por

<property name="hibernate.c3p0.idle_test_period">90</property><!-- troquei para 1 min e 30s para não levar tanto tempo para recuperar a conexão-->

você deve resolver o problema.

Se ainda não der, você pode tentar passar o gerenciamento das conexões para o servidor.

[]´s
Daniel

ativa

humm entendi… vou tentar isso. e observar para ver o que acontece…
e como eu passaria o gerenciamento das conexoes para o servidor?

ah, estou com outro problema que é o seguinte:
eu abro várias threads de armazenamento com o banco, em torno de 400 de uma vez. E estou obtendo a msg no exception de que o mysql nao pode instanciar a thread(acredito q pelo numero de conexoes, ja q cada thread abre uma conexao. Porem o número de conexoes configuradas no myslq é de 2000. o que pode estar ocorrendo neste caso tb?

vlw

abraçao!

yorgan

Cara, limita esse número de conexões.
Se tiver o min_size com 5 e o max com 20, para aplicações pequenas isso já ta bom d+.
Se você tiver com o sistema utilizando mais do que isso, ainda mais em ambiente de testes, você está com sérios problemas no gerenciamento de conexões.
Fora que, já li alguma coisa falando que cada conexão consome em média 2mb de ram. Se isso for verdade e você tiver um limite de 3000 conexões, é só fazer as contas para perceber que você vai precisar de um servidor com uma excelente configuração.

E sobre as conexões gerenciadas pelo servidor, deixa eu responder isso melhor no final de semana. Agora está um pouco complicado.

[]´s
Daniel

ativa

entendi…
entao, na verdade o sistema que estou usando é um pouco bruto.
é um servidor que se conecta à equipamentos para fazer telemetria.
aí para cada equipamento, eu tenho uma thread que fica comunicando o tempo todo, baixando as leituras e gravando no banco de dados.
as leituras sao baixadas de 10…10 segundos. e a cada vez que se baixa leituras, é aberta uma thread de armazenamento para gravar as leituras no banco de dados.
na maior parte do tempo, está em execuçao a umas 300 threads gravando no banco simultaneamente. Mas existe um momento em que há uma operaçao diferente de leitura dos equipamentos em que para cada equipamento sao abertas umas 15 threads de armazenamento. sendo assim, fica em torno de 3000 threads de gravando no banco.
ao fim da gravaçao as threads fecha e encerram a conexao com o banco.
mas nesse momento que as threads estao em execuçao, várias delas dá problema do mysql abrir thread de conexao, ou da cannot open conection.
esse é um problema que estou enfrentando.

agora o primeiro problema que é o problema do banco cair literalmente ta me tirando noites de sono, pq tive implementar um sistema pra me enviar sms quando o banco cair, aí quase todo dia de madrugada eu acordo com sms de que o banco de dados caiu.
aí eu tenho que fechar o software e abrir denovo para voltar a ler normalmente.

Sem problemas meu amigo. Quando vc puder eu agradeço.

Grande abraço!

ativa

Pessoal, estive estudando e googlando mas nao consegui nada ainda de avanço.

riccaio, meu stack trace nao traz broken pipe.
Estranho isso que acontece… o software fica funcionando e depois de aprox 12hs pára a comunicaçao com o banco. se eu reiniciar o software volta ao normal. A mensagem que vem quando imprimo o e.getMessage é “Cannot open connection”

yorgan, vc conseguiu algo pra me ajudar?

ta dando desespero ja isso :cry:

abraço galera!

Criado 7 de outubro de 2010
Ultima resposta 15 de out. de 2010
Respostas 8
Participantes 3