Pregunta

Recientemente cambié a Spring Framework en lugar de manejar manualmente JDBC, y es principalmente una buena transición. Sin embargo, un programa comenzó a tener problemas extraños: si la base de datos es lenta, al llamar a getJdbcTemplate (). Update (...) , a veces nunca regresa.

Después de investigar un poco, cambié de Apache DBCP a C3PO , pero el problema persiste regresó.

Aquí está el código que estoy usando:

public class MyDao extends SimpleJdbcDaoSupport {
    private static Logger logger = Logger.getLogger(MyDao.class);

    public MyDao(Config config) {
        super();

        ComboPooledDataSource cpds = new ComboPooledDataSource();
        try {
            cpds.setDriverClass("com.mysql.jdbc.Driver");
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        }
        cpds.setUser("username");
        cpds.setPassword("password");
        cpds.setJdbcUrl("jdbc:mysql://localhost/schema" + 
                        "?useUnicode=true&characterEncoding=UTF-8");
        cpds.setMaxStatements( 180 );
        cpds.setPreferredTestQuery("SELECT 1");
        cpds.setTestConnectionOnCheckout(true);

        this.setDataSource(cpds);
    }

    public void addToWorkQueue(String item) {
        long[] ids = Utils.getItemIds(item);

        try {
            logger.debug("About to insert to work table");
            getJdbcTemplate().update(
                    "INSERT IGNORE INTO work " +
                    "SELECT * FROM queue WHERE id_1 = ? AND id_2 = ?",
                    new Object[] { ids[0], ids[1] }
            );
        } finally {
            logger.debug("Updated work table");
        }
    }
}

Esto es lo que parece en el archivo de registro:

2009-07-29 17:37:13.570 com.mycomp.MyDao About to insert into work table
2009-07-29 17:37:13.570 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@170984c] on CHECKOUT.
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@170984c] on CHECKOUT has SUCCEEDED.
2009-07-29 17:37:13.571 com.mchange.v2.resourcepool.BasicResourcePool trace com.mchange.v2.resourcepool.BasicResourcePool@d402dd [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@170984c)
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache ----> CACHE HIT
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 1; num connections: 1; num keys: 1

Aquí es donde se cuelga el código. Por lo general, simplemente sigue así:

2009-07-29 17:37:13.762 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1
2009-07-29 17:37:13.763 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1
2009-07-29 17:37:13.763 com.mchange.v2.resourcepool.BasicResourcePool trace com.mchange.v2.resourcepool.BasicResourcePool@d402dd [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@170984c)
2009-07-29 17:37:13.763 com.mycomp.MyDao Updated work table

No sé por qué no recibo ningún mensaje de registro de Spring Framework. Agregué estas líneas en mi código principal:

Logger springLogger = Logger.getLogger("org.springframework");
springLogger.setLevel(Level.TRACE);
springLogger.debug("testing spring logger");

El mensaje de prueba muestra, pero nada más. Perdón por divergir.

Noté una desaceleración antes del bloqueo. La última vez que la consulta se ejecutó correctamente, tardó un minuto y medio en finalizar, en lugar de los 200 ms habituales. La próxima vez, lo dejé correr durante 25 minutos antes de finalizar el proceso.

Sé que tengo algunos problemas con mi base de datos (InnoDB), en la que estoy trabajando, pero parece que después de un tiempo de espera, Spring Framework simplemente "se da por vencido". y se cuelga.

Cualquier consejo sería apreciado.

¿Fue útil?

Solución

Finalmente, el problema se evitó solucionando el problema subyacente de la base de datos.

Estaba usando una tabla InnoDB como una cola de trabajo, lo que significaba que agregué y eliminé muchos elementos. La tabla nunca tuvo demasiadas filas en un momento dado, pero aparentemente InnoDB no puede manejar este tipo de trabajo, o como lo expresó mi amigo del DBA, "eliminar filas de una tabla no hace nada para el rendimiento".

Después de cambiar a una estrategia de base de datos mucho más loca, que implicaba crear y soltar tablas todo el tiempo, el rendimiento mejoró mucho y los bloqueos desaparecieron.

Entonces, supongo que lo que digo es que el comentario de skaffman probablemente fue correcto. Esto no tuvo nada que ver con Spring.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top