Как корректно закрыть MySQL соединение (что бы не было sleep) C#?

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113
Доброго времени. Работаю с базой данных MySQL через C#, пример статьи как это делать - брал отсюда. Все бы ничего, да возникла проблема, если в общий код мы добавляем для корректной работы:
Общий Код:
using MySql.Data.MySqlClient;
using MySql.Data;

    public class DB
    {



        private string hostname;
        private string username;
        private string password;
        private string database;
        private string charset;
        private string result;
        private MySqlConnection conn;

        //
        public DB(string db_hostname, string db_username, string db_password, string db_database, string db_charset = "utf8")
        {
            hostname = db_hostname;
            username = db_username;
            password = db_password;
            database = db_database;
            charset = db_charset;
            result = String.Empty;
            string db_port = "3306";

            var m = db_hostname.Split(':');
            if (m.Length == 2)
            {
                db_hostname = m[0];
                db_port = m[1];
            }

            var connectionString = "server=" + db_hostname + ";user=" + db_username + ";database=" + db_database + ";port=" + db_port + ";password=" + db_password + ";pooling=true;" + "charset=" + charset + ";";
            conn = new MySqlConnection(connectionString);

            open();
        }


        public void open()
        {
            conn.Open();
        }


        public void close()
        {
            conn.Close();
            //conn.Dispose();
            //MySqlConnection.ClearAllPools();
        }

        public void query(string query)
        {
            using (MySqlCommand command = new MySqlCommand(query, conn))
            {
                command.ExecuteNonQuery();
            }
        }

        public List<string> getAll(string query, string fieldSeparator = "|")
        {

            var result = new List<string>();

            MySqlCommand command = new MySqlCommand(query, conn);

            MySqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                List<string> fields = new List<string>();
                for (int i = 0; i<reader.FieldCount; i++)
                    fields.Add(reader[i].ToString());

                result.Add(string.Join(fieldSeparator, fields));

            }
            reader.Close();

            return result;
        }

        public List<string> getRow(string query)
        {

            MySqlCommand command = new MySqlCommand(query, conn);

            MySqlDataReader reader = command.ExecuteReader();

            if (reader.Read())
            {

                List<string> result = new List<string>();
                for (int i = 0; i<reader.FieldCount; i++)
                    result.Add(reader[i].ToString());

                reader.Close();
                return result;
            }

            reader.Close();
            return new List<string>();
        }


        public string getOne(string query)
        {
            MySqlCommand command = new MySqlCommand(query, conn);
            string result = "";
            try
            {
                result = command.ExecuteScalar().ToString();
            } catch
            {
            }
            return result;
        }


        public string escapeString(string text)
        {
            return MySql.Data.MySqlClient.MySqlHelper.EscapeString(text);
        }

    }
А потом Zenno-кубике используем примерно такое:
95102
То в таком случае, в многопотоке мы получаем вот такую картину:
95101
На скрине выше видно, что соединения не прерваны, а просто ушли в Sleep(Спать), что не очень хорошо в многопотоке, так как очень сильно нагружает хостинг и потом возникают проблемы.

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

Wide

Client
Регистрация
04.02.2013
Сообщения
945
Благодарностей
257
Баллы
63
LOCK TABLES;
...
UNLOCK TABLES;
 

gelu4

Client
Регистрация
11.01.2015
Сообщения
166
Благодарностей
42
Баллы
28
У меня похожая проблема, хотя код другой. Приходится примерно раз в месяц заходить через phpmyadmin и вручную "убивать" все коннекты, так и не смог найти утечку(
 

Sherminator

Client
Регистрация
10.09.2021
Сообщения
1 261
Благодарностей
679
Баллы
113
Доброго времени. Работаю с базой данных MySQL через C#, пример статьи как это делать - брал отсюда. Все бы ничего, да возникла проблема, если в общий код мы добавляем для корректной работы:
Общий Код:
using MySql.Data.MySqlClient;
using MySql.Data;

    public class DB
    {



        private string hostname;
        private string username;
        private string password;
        private string database;
        private string charset;
        private string result;
        private MySqlConnection conn;

        //
        public DB(string db_hostname, string db_username, string db_password, string db_database, string db_charset = "utf8")
        {
            hostname = db_hostname;
            username = db_username;
            password = db_password;
            database = db_database;
            charset = db_charset;
            result = String.Empty;
            string db_port = "3306";

            var m = db_hostname.Split(':');
            if (m.Length == 2)
            {
                db_hostname = m[0];
                db_port = m[1];
            }

            var connectionString = "server=" + db_hostname + ";user=" + db_username + ";database=" + db_database + ";port=" + db_port + ";password=" + db_password + ";pooling=true;" + "charset=" + charset + ";";
            conn = new MySqlConnection(connectionString);

            open();
        }


        public void open()
        {
            conn.Open();
        }


        public void close()
        {
            conn.Close();
            //conn.Dispose();
            //MySqlConnection.ClearAllPools();
        }

        public void query(string query)
        {
            using (MySqlCommand command = new MySqlCommand(query, conn))
            {
                command.ExecuteNonQuery();
            }
        }

        public List<string> getAll(string query, string fieldSeparator = "|")
        {

            var result = new List<string>();

            MySqlCommand command = new MySqlCommand(query, conn);

            MySqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                List<string> fields = new List<string>();
                for (int i = 0; i<reader.FieldCount; i++)
                    fields.Add(reader[i].ToString());

                result.Add(string.Join(fieldSeparator, fields));

            }
            reader.Close();

            return result;
        }

        public List<string> getRow(string query)
        {

            MySqlCommand command = new MySqlCommand(query, conn);

            MySqlDataReader reader = command.ExecuteReader();

            if (reader.Read())
            {

                List<string> result = new List<string>();
                for (int i = 0; i<reader.FieldCount; i++)
                    result.Add(reader[i].ToString());

                reader.Close();
                return result;
            }

            reader.Close();
            return new List<string>();
        }


        public string getOne(string query)
        {
            MySqlCommand command = new MySqlCommand(query, conn);
            string result = "";
            try
            {
                result = command.ExecuteScalar().ToString();
            } catch
            {
            }
            return result;
        }


        public string escapeString(string text)
        {
            return MySql.Data.MySqlClient.MySqlHelper.EscapeString(text);
        }

    }
А потом Zenno-кубике используем примерно такое:
То в таком случае, в многопотоке мы получаем вот такую картину:
На скрине выше видно, что соединения не прерваны, а просто ушли в Sleep(Спать), что не очень хорошо в многопотоке, так как очень сильно нагружает хостинг и потом возникают проблемы.

Как же можно решить данную проблему, что бы нормально закрывались соединения без попадания в сон, а сразу же полностью вырубались?
Попробуй в конекшн стринг вот это добавить Pooling=False точнее не добавить, а в своей строке изменить true на false это тип пул конекшенов, и что бы они там не спали надо его просто вырубить. При этом создание экземпляра подключения рекомендуется заворачивать в конструкцию using
 
Последнее редактирование:
  • Спасибо
Реакции: Viktor111 и gelu4

one

Client
Регистрация
22.09.2015
Сообщения
6 833
Благодарностей
1 275
Баллы
113
Статья была на форуме и обсуждение о закрытии соединений к БД.
 

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113

one

Client
Регистрация
22.09.2015
Сообщения
6 833
Благодарностей
1 275
Баллы
113

Sherminator

Client
Регистрация
10.09.2021
Сообщения
1 261
Благодарностей
679
Баллы
113
Можно пожалуйста пример как это сделать?
А отключение пулов не помогло?
Ну в целом суть такая, класс MySqlConnection реализует интерфейс IDisposable в котором (речь про класс конекшн) реализован метод Dispose(), в этом методе определена "зачистка" для этого класса.
Таким образом можно подобный экземпляр класса, который наследует этот интерфейс, реализовать в конструкции юзинг.

C#:
using(MySqlConnection  connection = new MySqlConnection )  //создаем тут экземпляр класса

{

//Тут мы выполняем нужные нам работы связанные с созданным нами экземпляром класса

}

/* И как только код выходит за фигурный скобки конструкции юзинг,
невидимо для нас автоматически срабатывает метод Dispose() которые определен
в классе конекшн и в котором реализована требуемая для этого класса зачистка.*/
Суть в том, что с такими вещами как базы данных или стримы принято работать через using, что бы процессы проходящие в них корректно убивались и в дальнейшем по мере продвижения кода не возникало проблем с не закрытой базой данных или стримом. Для этого подобные классы уже наследуют интерфейс IDisposable и реализую метод Dispose() таким образом как это требуется для данного класса. В итоге и велосипед изобретать не надо, разрабы уже все сделали.
 
Последнее редактирование:

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113
А отключение пулов не помогло?
Ну в целом суть такая, класс MySqlConnection реализует интерфейс IDisposable в котором (речь про класс конекшн) реализован метод Dispose(), в этом методе определена "зачистка" для этого класса.
Таким образом можно подобный экземпляр класса, который наследует этот интерфейс, реализовать в конструкции юзинг.

C#:
using(MySqlConnection  connection = new MySqlConnection )  //создаем тут экземпляр класса

{

//Тут мы выполняем нужные нам работы связанные с созданным нами экземпляром класса

}

/* И как только код выходит за фигурный скобки конструкции юзинг,
невидимо для нас автоматически срабатывает метод Dispose() которые определен
в классе конекшн и в котором реализована требуемая для этого класса зачистка.*/
Суть в том, что с такими вещами как базы данных или стримы принято работать через using, что бы процессы проходящие в них корректно убивались и в дальнейшем по мере продвижения кода не возникало проблем с не закрытой базой данных или стримом. Для этого подобные классы уже наследуют интерфейс IDisposable и реализую метод Dispose() таким образом как это требуется для данного класса. В итоге и велосипед изобретать не надо, разрабы уже все сделали.
К сожалению понятнее не стало. Что и куда.
1. То ли код из Раздела общего кода засунуть в using в раздел Директивы Using:
95119
2. Или в Дерективы Using засунуть using ваш код и там открывать коннект с кодом из зеннокубика.
3. Или в C# зеннокубик как то использовать данный using.
4. Или в Разделе общего кода как-то прицепить этот using.

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

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18
Никогда не замечал такой проблемы, код использую тоже из той темы, pooling=False
 

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18
Код из зеннокубика тоже такой же?
Примерно такой
C#:
DB db = new DB(db_host, db_user, db_pswd, db_database, db_charset);
project.Context["db"] = db;
db.query($"LOCK TABLES {table} WRITE");
//работа с бд

db.query("UNLOCK TABLES");
И по good/bad end вызываю db.close();
Еще не уверен нужно ли лочить таблицы каждый раз, вроде они и так должны лочиться
 

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113
Примерно такой
C#:
DB db = new DB(db_host, db_user, db_pswd, db_database, db_charset);
project.Context["db"] = db;
db.query($"LOCK TABLES {table} WRITE");
//работа с бд

db.query("UNLOCK TABLES");
И по good/bad end вызываю db.close();
Еще не уверен нужно ли лочить таблицы каждый раз, вроде они и так должны лочиться
Ну лок на сколько я понимаю, в моем случае ничего не даст, так как останется тот же слип.
 

Sherminator

Client
Регистрация
10.09.2021
Сообщения
1 261
Благодарностей
679
Баллы
113
К сожалению понятнее не стало. Что и куда.
1. То ли код из Раздела общего кода засунуть в using в раздел Директивы Using:
2. Или в Дерективы Using засунуть using ваш код и там открывать коннект с кодом из зеннокубика.
3. Или в C# зеннокубик как то использовать данный using.
4. Или в Разделе общего кода как-то прицепить этот using.

Если нету желания бесплатно обьяснять, напишите пожалуйста в телеграм, обсудим бюджет на решение данной задачи.
Директива using ( using MySql.Data) и оператор using (про который мы говорим) это совершенно разный вещи. оператор юсинг надо размещать внутри класса.

у тебя в том коде что ты прислал даже используется подобная конструкция в одном из методов.
2022-07-28_14-31-39.png


У тебя еще в коде вот тут


C#:
      public void close()
        {
            conn.Close();
            //conn.Dispose();
            //MySqlConnection.ClearAllPools();
        }

закоменчен вызов как раз метода диспос и очистки пула, ты пробовал вот так?
C#:
      public void close()
        {
            conn.Close();
            conn.Dispose();
            MySqlConnection.ClearAllPools();
        }
По большому счету нету разницы каким образом на экземпляре класса будет вызван этот метод, через using или вот так вот руками, так что попробуй сначала раскомментировать этот код и с ним выполниться
 
Последнее редактирование:

Gunjubasik

Client
Регистрация
30.05.2019
Сообщения
3 523
Благодарностей
1 321
Баллы
113
закоменчен вызов как раз метода диспос и очистки пула, ты пробовал вот так?
Да, пробовал, не помогло. Закоментировал перед добавлением сюда, что бы не было вопросов зачем я это использую.
 
Последнее редактирование:

Sherminator

Client
Регистрация
10.09.2021
Сообщения
1 261
Благодарностей
679
Баллы
113
  • Спасибо
Реакции: Gunjubasik

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)