Conexao com o banco de dados trava ao cair a internet

4 respostas
Arthur.hvt

Olá :D

O meu programa faz o seguinte: Faz um select num banco de dados externo, pega uns dados e logo depois faz um update no banco local e outro update no banco externo. Vendo o código da pra entender melhor:

public synchronized void sincronizarAcumulados(List<Acumulado> acumulados) throws Exception {

        ResultSet rs = null;
        Connection conexao = null;
        PreparedStatement ps = null;

        try {
            conexao = ConnectionFactory.getConexaoExterna();

            for (Acumulado acumulado : acumulados) {

                //só entra se o valor que tem pra sincronizar for maior que zero
                if (acumulado.getToSync().compareTo(BigDecimal.ZERO) == 1) {
                    ps = conexao.prepareStatement("SELECT base, teto, valor FROM acumulados WHERE id_loja = ? LIMIT 1");

                    ps.setInt(1, Main.casa.getId());

                    ps.execute();

                    rs = ps.getResultSet();

                    while (rs.next()) {
                        double base = rs.getDouble(1);
                        double teto = rs.getDouble(2);
                        double valor = rs.getDouble(3);

                        acumulado.setBase(new BigDecimal(base));
                        acumulado.setTeto(new BigDecimal(teto));
                        acumulado.setValor(new BigDecimal(valor).add(acumulado.getToSync())); //adiciona o valor que tem que ser sincronizado

                        atualizar(acumulado);
                    }
                }
            }
        } catch (Exception e) {
            throw new Exception("Erro ao tentar sincronizar os acumulados", e);
        } finally {
            ConnectionFactory.closeConnection(conexao, ps, rs);
        }
    }



    private void atualizar(Acumulado acumulado) {

        PreparedStatement psLocal = null;
        PreparedStatement psExterno = null;

        Connection conexaoLocal = null;
        Connection conexaoExterna = null;

        Savepoint saveLocal = null;
        Savepoint saveExterno = null;

        try {
            conexaoLocal = ConnectionFactory.getConexaoLocal();
            conexaoExterna = ConnectionFactory.getConexaoExterna();

            conexaoLocal.setAutoCommit(false);
            conexaoExterna.setAutoCommit(false);

            saveLocal = conexaoLocal.setSavepoint();
            saveExterno = conexaoExterna.setSavepoint();

            //UPDATE EXTERNO
            psExterno = conexaoExterna.prepareStatement("UPDATE acumulados SET valor=? WHERE id_loja=?",
                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);

            psExterno.setDouble(1, acumulado.getValor().doubleValue());
            psExterno.setInt(2, Main.config.getIdLoja());

            psExterno.executeUpdate();

            //UPDATE LOCAL
            psLocal = conexaoLocal.prepareStatement("UPDATE acumulado SET base=?, teto=?, valor=?, to_sync=(IF(to_sync>0,to_sync-?,0));",
                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);

            psLocal.setDouble(1, acumulado.getBase().doubleValue());
            psLocal.setDouble(2, acumulado.getTeto().doubleValue());
            psLocal.setDouble(3, acumulado.getValor().doubleValue());
            psLocal.setDouble(4, acumulado.getToSync().doubleValue());

            psLocal.executeUpdate();

            conexaoExterna.commit();
            conexaoLocal.commit();
        } catch (Exception e) {
            Config.logger.error("Erro ao fazer atualizacao do acumulado. Tentando novamente...", e);

            try {
                if (saveLocal != null) {
                    conexaoLocal.rollback(saveLocal);
                }

                if (saveExterno != null) {
                    conexaoExterna.rollback(saveExterno);
                }
            } catch (SQLException ex) {
                Config.logger.error("Erro ao fazer rollback da atualizacao de acumulados", ex);
            }

            atualizar(acumulado);
        } finally {
            ConnectionFactory.closeConnection(conexaoLocal, conexaoExterna, psLocal);
        }
    }

O código acima roda tranquilamente. O problema é quando a internet cai enquando esta sendo feito o processo. O programa fica parado por muito tempo (de 15 a 30 min depois que a internet voltou). Logo depois do tempo da uma exception e volta a rodar. A exception é:

CommunicationsException: Communications link failure

The last packet successfully received from the server was 1,011,822 milliseconds ago.  The last packet sent successfully to the server was 1,010,609 milliseconds ago.

Agradeço a ajuda.

4 Respostas

Dakon

Cria um timer que cheque o estado da thread e “mate-a” em um tempo limite…

Arthur.hvt

Eu tinha pensado nisso, mas queria uma solucao que fizesse com que o processo continuasse apos a volta da conexao. E alem do mais eu nao tenho como fazer umempo limite, porque em muitos casos o processo de sincronizacao demora muito por conexao lenta.

mauricioadl

o problema eh que quando a conexao cai vc tenta dar um rollback nela, que fica ainda pior. tente tratar o CommunicationsException separadamente. fazendo isso vc bota um timer pra voltar o processo.

[]'s

Arthur.hvt

Isso nao resolve porque só ocorre a exceção depois que sair do lock (15 a 20 min). Eu estava pensando em colocar um ConnectionReaper (http://java.sun.com/developer/onlineTraining/Programming/JDCBook/conpool.html#dead), mas a validação sempre retorna true…

Criado 27 de março de 2012
Ultima resposta 28 de mar. de 2012
Respostas 4
Participantes 3