В одном из наших унаследованных приложений произошла утечка базы данных, и я отследил ее до этого маленького драгоценного камня. От отладки я могу видеть, что такое же логическое соединение возвращается для нескольких потоков (не хорошо!). Но я пытаюсь понять, почему это происходит.Укажите проблему параллелизма
Мы используем драйвер ojdbc6, настроенный на источник данных WebLogic с пулом соединений.
Код, который производит проблему
public class MyDummyDaoUtil {
//note: this is a public field in a singleton (not a static field though...)
public Connection conn;
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
//the same logical connection is produced by the data source or something else happening?
conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
Обновлено FIX
public class MyDummyDaoUtil {
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
Connection conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
Резюме затруднительного
- Некорректное ленивым initializa Тион экземпляра
- Подключение должно быть локальной переменной в методе, а не класс синглтон
Вы говорите, что MyDummyDaoUtil - синглтон. Если это общий доступ к нескольким потокам, тогда будет возможность запросить два соединения, которые могут быть изменены с использованием ссылки и той же ссылки (последней), которая была возвращена из обоих вызовов в getDBConnection. Соединение, которое не было возвращено, никогда не может быть закрыто. Был ли этот код не исчерпывать доступные соединения? – Yoztastic
@Yoztastic Связи, вероятно, были сбиты их финализатором, когда они были собраны мусором, скрывая эту проблему. – Durandal
@Yoztastic - Да, это был первоначальный симптом. Наши связи были исчерпаны, и нам пришлось включить неактивный таймаут, чтобы помочь восстановить эти утеченные соединения, пока мы отслеживаем проблему. Из того, что я могу сказать, код был реализован таким образом с первого дня (что страшно ...) Непонятно, как эта проблема не отображалась в нашей старой системе. Я предполагаю, что связи были восстановлены как-то, и мы не понимали, что эта проблема существует. – user1766760