jdbcTemplate зависает при длительном обновлении

StackOverflow https://stackoverflow.com/questions/1200852

  •  05-07-2019
  •  | 
  •  

Вопрос

Я недавно переключился на Spring Framework вместо ручной обработки JDBC, и это в основном хороший переход. У одной программы начались странные проблемы: если база данных работает медленно, при вызове getJdbcTemplate (). Update (...) иногда она никогда не возвращается.

После небольшого исследования я переключился с Apache DBCP на C3PO , но проблема все еще вернулся.

Вот код, который я использую:

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");
        }
    }
}

Вот как это выглядит в файле журнала:

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

Это где код висит. Обычно это просто так:

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

Я не знаю, почему я не получаю никаких сообщений журнала от самой Spring Framework. Я добавил эти строки в свой основной код:

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

Тестовое сообщение показывает, но больше ничего. Извините за расхождение.

Я заметил замедление перед зависанием. В прошлый раз, когда запрос выполнялся успешно, потребовалось полторы минуты, вместо обычных 200 мс. В следующий раз, я позволил ему работать в течение 25 минут, прежде чем убить процесс.

Я знаю, что у меня есть некоторые проблемы с моей базой данных (InnoDB), над которой я работаю, но, похоже, по истечении тайм-аута, Spring Framework просто "сдается" и зависает.

Любой совет будет оценен.

Это было полезно?

Решение

В конце концов, проблему удалось избежать, исправив проблему с базой данных.

Я использовал таблицу InnoDB в качестве рабочей очереди, что означало, что я добавил и удалил в нее множество элементов. В таблице никогда не было слишком много строк в данный момент времени, но, очевидно, InnoDB не может справиться с такой работой, или, как сказал мой друг DBA, «удаление строк из таблицы ничего не делает для производительности».

После перехода на гораздо более безумную стратегию БД, которая включала в себя создание и удаление таблиц все время, производительность значительно улучшилась, и зависания исчезли.

Так что, я думаю, что комментарий Скаффмана, вероятно, был правильным. Это не имеет ничего общего с Spring.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top