WebApp (Tomcat-jdbc) Объединенное исключение блокировки подключения к базе данных

Я некоторое время просматривал SO и пережевывал шляпу в процессе, но не могу найти точное совпадение с моей проблемой.
Короче говоря, я получаю превосходную трассировку стека (org.apache.tomcat.jdbc.pool.ConnectionPool) после 60 секунд бездействия, что является нормальным поведением для нескольких потоков на стороне сервера.
Я использую Tomcat JDBC Connection Pooling (org.apache.tomcat.jdbc.pool.DataSource) напрямую
Трассировка стека:

    Oct 29, 2012 8:55:50 PM org.apache.tomcat.jdbc.pool.ConnectionPool abandon
    WARNING: Connection has been abandoned PooledConnection[[email protected]]:java.lang.Exception
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:967)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:721)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111)
        at com.getsom.getConnection(DAO.java:1444)
        at com.getsom.PreparedConnection.(PreparedConnection.java:48)
        at com.getsom.Alarms.run(Alarms.java:492)

Мои свойства PoolProperties настроены следующим образом:

    PoolProperties pp = new PoolProperties();

    pp.setUrl( someValidUrl);
    pp.setDriverClassName("com.mysql.jdbc.Driver");
    pp.setUsername( someUser);
    pp.setPassword( somePassword);
    pp.setJmxEnabled( true);
    pp.setTestWhileIdle( true);
    pp.setTestOnBorrow( true);
    pp.setValidationQuery( "SELECT 1");
    pp.setTestOnReturn( false);
    pp.setValidationInterval(30000);
    pp.setTimeBetweenEvictionRunsMillis(30000);
    pp.setMaxActive(100);
    pp.setInitialSize(10);
    pp.setMaxWait(10000);
    pp.setMinEvictableIdleTimeMillis(30000);
    pp.setMinIdle(10);

    pp.setLogAbandoned(true);
    pp.setRemoveAbandoned(true);
    pp.setRemoveAbandonedTimeout(60);
    pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");    

    setPoolProperties(pp);

Я надеялся, что setValidationInterval (30000) спасет меня, поскольку 30-е годы не так много в жизненном цикле связи. В любом случае, вопрос:
Что мне не хватает, чтобы поддерживать это соединение навсегда?
Приятно знать: почему я тайминг в функции, которая заявила о соединении, хотя она была вызвана на 30 секунд раньше.

Ответ 1

Несмотря на то, что я нахожусь на 1 год позже на этой странице, я все же споткнулся, потому что у меня возникли подобные проблемы, и мне тоже нужно решение. Поэтому я думал, что поделюсь тем, что в конечном итоге сработало для меня.

В моем случае, после поиска и чтения этой статьи → > configuring-jdbc-pool-high-concurrency - я просто добавил такой перехватчик в конфигурацию моего пула;

"org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"

чтобы строка (из вашего опубликованного кода выше), где вы делаете setJdbcInterceptors(...), теперь должна выглядеть следующим образом:

p.setJdbcInterceptors(
            "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
            + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
            + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");

Объяснение. В цитате из статьи говорится:

Мы хотим убедиться, что когда мы обнаруживаем, что соединение все еще используется, мы reset таймер тайм-аута, чтобы соединение не считалось заброшенным. Мы делаем это, вставляя перехватчик.

Каждый раз, когда оператор готов или выполняется запрос, таймер будет reset таймером останова в пуле подключений. Таким образом... выполнение большого количества запросов и обновлений не будет тайм-аутом.

Принимая во внимание, что вы, скорее всего, давно преодолели проблему, я все еще надеюсь, что это поможет кому-то еще иметь похожие проблемы, которые сталкиваются с этой страницей, как и я.

Ура!

Ответ 2

Вы видели информацию на веб-сайте Tomcat, относящуюся к PoolConnection. Возможно, вам нужно посмотреть на свойство minEvictableIdleTimeMillis

Чтобы ответить на ваш вопрос, вы выбрали время, потому что вы проверяете простоя и отказываетесь от подключений каждые 30 секунд (см. TimeBetweenEvictionRunsMillis), и поскольку вы устанавливаете вычитаемый тайм-аут простоя через 30 секунд (см. minEvictableIdleTimeMillis), вы заканчиваете с тем, что у вас есть. Вы сказали, что получаете это исключение в режиме ожидания, я подозреваю, что это исключение является результатом закрытия простоя соединения, а не отказа от подключения. По моему мнению, отказ от подключения используется для выключения более длинных ожиданий (в отличие от простоя соединений).

Лично я не хотел бы иметь связи живыми навсегда, потому что они будут потреблять ресурсы (то есть соединение с db) без необходимости. Я бы играл с моими максимальными соединениями, выселениями и простоями, чтобы оптимизировать свои собственные требования. Я думаю, вы можете установить эти значения достаточно большими, чтобы они были навсегда! Это действительно зависит от того, что вы делаете, хотя...

Извините, я больше не мог помочь.

Ответ 3

Просто добавьте следующую запись в tomcat7 conf/server.xml или в context.xml, где присутствует ваш тег ресурса.

jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"

Ответ 4

track 'removeAbandonedTimeout' в файле конфигурации. это должен быть максимальный запуск запроса в приложении. в противном случае он будет закрывать соединение в середине выполнения

Ответ 5

Если вы определяете свой источник данных в файле context.xml tomcat, вы должны добавить ResetAbandonedTimer, как показано ниже:

jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"

После установки ResetAbandonedTimer проблема разрешилась в моем приложении, попросив сообщить мне, существует ли какая-либо связь между перехватчиком ResetAbandonedTimer и removeAbandoned = "true" removeAbandonedTimeout = "60"

Ответ 6

Ответы на этот вопрос были очень полезны для меня.

Хотя в моем случае у меня уже был настроен перехватчик JDBC "ResetAbandonedTimer".

Однако у меня был запрос, который выполнялся дольше, чем "removeAbandonedTimeout", который я также настроил. Как только я увеличил "removeAbandonedTimeout", проблема исчезла.

Ответ 7

Была похожая проблема, т.е. Tomcat закрывал соединение JDBC из-за того, что оно было прервано из-за того, что транзакция заняла много времени.

Решил это, осознав, что abandoned и idle различны, и установив: spring.datasource.tomcat.removeAbandonedTimeout: 86400 #seconds

Ответ 8

Я вижу, что эта ветка старая, но у меня была похожая проблема, и в конце концов я нашел причину, которая ее вызвала, поэтому я хотел бы поделиться, если она может кому-то помочь:

Я использовал соединение из спокойного веб-сервиса. В интерфейсе на стороне сервера, обрабатывающем запрос от клиента, я случайно добавил "throws IOException" в сигнатуру метода:

@GET
@Path("/databases")
@Produces(MediaType.APPLICATION_JSON)
public String getAllDatabases() throws IOException {