DBCP возвращает закрытые соединения - PullRequest
5 голосов
/ 08 сентября 2011

Мы наблюдаем ситуации, когда соединение с нашей базой данных из org.apache.commons.dbcp.BasicDataSource умирает с ошибками записи в сокет:

com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: socket write error

Все последующие попытки записи в соединение терпят неудачу, конечно:

com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.

После обновления кода, чтобы перехватить такие исключения и запросить новое соединение, когда оно происходит, оно снова не удалось. Правильно ли я подозреваю, что вызов DataSource#getConnection() фактически не дает новое соединение каждый раз, когда он вызывается? Разве это не просто повторное использование существующего соединения, которое закрыто?

Если я прав, как правильно отбросить старое соединение и запросить новое?

РЕДАКТИРОВАТЬ: Вот более лаконичная версия того, что я хотел бы знать:

Connection c1, c2;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c2 = DatabaseManager.getConnection(); 

Является ли "c1 == c2" верным утверждением? Или было выделено два соединения? И если это последнее, будет ли такой код представлять собой «утечку пула соединений»:

Connection c1;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c1 = DatabaseManager.getConnection();

Ответы [ 2 ]

10 голосов
/ 08 сентября 2011

Соединение в пул было закрыто БД. Это может означать 2 вещи:

  1. Пул соединений слишком долго удерживает открытыми соединения.
  2. БД закрывает соединения через слишком короткое время.

Теоретически, увеличение / уменьшение времени ожидания с обеих сторон для его выравнивания должно решить проблему.

На DBCP лучше всего проверять соединения перед возвратом с помощью настроек testOnBorrow=true и validationQuery, например. SELECT 1. Вы можете найти параметры конфигурации в документации по источникам данных Tomcat JDBC .


Обновление согласно вашему обновлению:

Вот более лаконичная версия того, что я хотел бы знать:

Connection c1, c2;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c2 = DatabaseManager.getConnection(); 

Является ли "c1 == c2" верным утверждением? Или было выделено два соединения?

Это две разные связи. Только если вы позвоните c1.close(), тогда вполне вероятно, что c2 вернет то же соединение.

И если это последнее, будет ли такой код представлять собой «утечку пула соединений»:

Connection c1;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c1 = DatabaseManager.getConnection();

Да, определенно будет утечка первого соединения, поскольку оно никогда не было возвращено в пул. Вы должны всегда закрыть все ресурсы БД в кратчайшей возможной области в блоке try-finally. Тем не менее, неплохой пул соединений можно настроить для получения заброшенных соединений, но это определенно не должно использоваться в качестве «обходного пути».

1 голос
/ 25 апреля 2017

У меня тоже были такие же проблемы. затем я понял, что я делаю несколько асинхронных вызовов AJAX, которые вызывали проблему.

Я сериализировал звонки, и это устранило проблему.

...