Проблема с не закрытием соединения БД при отладке? - PullRequest
6 голосов
/ 23 января 2010

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

Это приведет к тому, что открытые соединения будут накапливаться и замедлять работу базы данных, или она будет очищена автоматически?

Ответы [ 4 ]

8 голосов
/ 23 января 2010

Соединение с базой данных принадлежит и управляется базой данных, класс просто предоставляет вам доступ к этому ресурсу базы данных. Если вы не закроете соединение, тогда класс Java может быть подвергнут сборке мусора, но база данных может не сказать, что соединение больше не используется, что может привести к потере ресурсов базы данных (до истечения времени ожидания на стороне базы данных). ) или даже утечка.

Итак, когда вы закончили использовать Connection, вы должны быть уверены, , что явно закроете его, вызвав его метод close(). Это позволит сборщику мусора восстановить память как можно раньше и, более важно , освободит любые другие ресурсы базы данных (курсоры, дескрипторы и т. Д.), Которые может удерживать соединение.

Традиционный способ сделать это в Java - закрыть ваши ResultSet, Statement и Connection (в указанном порядке) в блоке finally, когда вы закончите с ними, и безопасный шаблон будет выглядеть что:

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try {
    // Do stuff
    ...

} catch (SQLException ex) {
    // Exception handling stuff
    ...
} finally {
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { /* ignored */}
    }
}

Блок finally можно немного улучшить (чтобы избежать проверки на ноль):

} finally {
    try { rs.close(); } catch (Exception e) { /* ignored */ }
    try { ps.close(); } catch (Exception e) { /* ignored */ }
    try { conn.close(); } catch (Exception e) { /* ignored */ }
}

Но, тем не менее, это чрезвычайно многословно, так что вы обычно используете вспомогательный класс для закрытия объектов в нулевых безопасных вспомогательных методах, и блок finally становится примерно таким:

} finally {
    DbUtil.closeQuietly(rs);
    DbUtil.closeQuietly(ps);
    DbUtil.closeQuietly(conn);
}

И, собственно, Apache Commons DbUtils имеет класс DbUtils, который точно делает это, поэтому нет необходимости писать свой собственный.

В вашем случае это решит проблему исключения, но не отладки (и вы будете тратить ресурсы базы данных до истечения времени ожидания на стороне базы данных). Итак, 1. не отлаживайте свой код с помощью производственной базы данных 2. попробуйте выполнить сеанс отладки до конца.

2 голосов
/ 23 января 2010

Вот что Sun (ошибается ... Oracle?) говорит :

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

Программист, пишущий код на языке программирования Java и не использующий какие-либо внешние ресурсы, не должен беспокоиться об управлении памятью. Сборщик мусора автоматически удаляет объекты, когда они больше не используются, и освобождает память, которую они использовали. Когда памяти не хватает, он будет перерабатывать отброшенные объекты, делая доступной в настоящее время память доступной для быстрого повторного использования.

Однако, если приложение использует внешние ресурсы, как это происходит, когда оно обращается к СУБД с помощью API JDBC, сборщик мусора не может узнать состояние этих ресурсов. Он по-прежнему будет перерабатывать отброшенные объекты, но если в куче Java имеется много свободной памяти, он может собирать мусор нечасто, даже если (небольшое) количество мусора Java удерживает открытые большие объемы дорогих ресурсов базы данных. Поэтому рекомендуется, чтобы программисты явно закрывали все соединения (с методом Connection.close) и операторы (с методом Statement.close), как только они больше не нужны, тем самым освобождая ресурсы СУБД как можно раньше. Это особенно относится к приложениям, предназначенным для работы с разными СУБД из-за различий между разными СУБД.

Я бы поставил доступ к базе данных в блок try и обязательно закрыл все операторы и соединения в блоке finally.

2 голосов
/ 23 января 2010

Ваш сервер БД будет иметь настройку тайм-аута. Он закроет соединение и откатит все незафиксированные транзакции. Это происходило в течение десятилетий с любым продуктом, способным к производству БД.

Если вы хотите сделать это правильно, используйте попытку {..your code ..} finally {..close соединений ..}

0 голосов
/ 23 января 2010

Нет.

Если ваша программа продолжается, а ваши соединения живы, BD просто отклонил ваше предложение.

Если что-то случилось с вашим соединением (например, тайм-аут), то BD был тем, кто закрыл это соединение, и он не потребляет ресурсы.

Если вы освободили свое соединение и был вызван сборщик мусора (это может занять некоторое время), соединение закроется само перед освобождением.

Если ваша программа была прервана без закрытия соединения, тогда весь процесс (операционной системы) освободит свои собственные ресурсы, а между ними - собственный ресурс, подключенный к BD (возможно, сетевой сокет). Затем BD получит соединение, прерванное / закрытое, и освободит ваше соединение.

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

Редактировать : в целом BD сделаны плохое поведение клиента -защищенные

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...