Падають тести з помилкою Too many connections

Написав тести на сервак (Java, Testng), в сумі вишло близько 200. Під час проходження їх, деякі тести подають з помилкою om.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections. Знаю, що в кожного сервака є виставлене своє максимальне число відкритий конекшенів - для зміни його треба робити задачку на адмінив і тд. Мені здається, що є інший спосіб контроювати якось кількість конекшенів до БД.

Зєднання з БД використувається таким методом:

public static Connection connectToDB() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
    }

Приклад запиту в БД:

public static int getUserId(String deviceId, int appId) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        int userId = 0;
        Statement st = connectToDB().createStatement();
        ResultSet vv = st.executeQuery("SELECT user_id FROM .........");

        while (vv.next()) {

            userId = vv.getInt("user_id");
        }
        st.close();
        connectToDB().close();
        return userId;
    }

Я пробував робити затримку через Thread.sleep(), але результат не змінився. Завжди вилітає помилка Too many connections на одинх і тих самих тестах.
Дану проблему гуглив, але чіткої відповіді не найшов (або не зрозумів). Підскажіть, хто стикався з такою проблемо і як її вирішив?

А getUserId() откуда дёргается? И где в методе используются deviceId и appId? зачем эти параметры?

Маю клас DataBaseQueries, в якому присутній метод connectToDB() і методи типу getUserId(String deviceId, int appId).
В методі getUserId(String deviceId, int appId) параметри deviceId і appId використовуються в SELECT, я їх видалив, так як це не має значення.

public class DataBaseQueries {
    static private String DB_URL = "";
    static private String DB_USER = "";
    static private String DB_PASS = "";

    public static Connection connectToDB() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
    }


    public static int getUserId(String deviceId, int appId) {
    }

    public static String getUserData(int userId){
    }
}

Тобто у вас під час запуску необхідно тримати таку велику кількість відкритих коннекшенів? Можливо варто спробувати їх закривати післ отриання відповіді, або використовувати один відкритий звязок з базою данних і його перевиконистовувати?

1 лайк

Та ні, не потрібно тримати відкриті конекшини. А що, в методі getUserId я не закриваю конекшин цим кодом

st.close();
connectToDB().close();

Это у тебя создает новый коннект и его закрывает а предыдущий ты не закрыл т.к. он у тебя:

исходя из этого нужно исправить:

connectToDB().close(); -> Statement.close();

Так я ж закриваю… Створюю обєкт Statement st, а в кінці метод закриваю його st.close(); + connectToDB().close();
Спробував поміняти місцями закриття connectToDB() і st - але нічого не змінилось.

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

Во-вторых, как уже отметили выше, - после закрытия стейтмента вы открываете новый конекшен и сразу же закрываете. Но старый, при этом, по-прежнему остается висеть. При вашей текущей реализации вы не сможете сделать иначе до тех пор, пока не вынесите конекшен на уровень инстанс филда.

1 лайк

Відкриваю один конекшин перед усіма тестами, і закриваю його після пройдених тестів.

@BeforeSuite
    public void openConection() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException {
        openConectionToDB();
    }

    @AfterSuite
    public void closeConection() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException {
        closeConectionToDB();
    }

методи close i open

public static void openConectionToDB() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException {
        st = connectToDB().createStatement();
    }

    public static void closeConectionToDB() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException {
        connectToDB().close();
        st.close();
    }

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

1 лайк

Вибач не туди подивився :slight_smile: