Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > пул соединений


Автор: kokcu 25.7.2010, 17:56
Здравствуйте. Есть приложение которое делает по таймерам несколько запросов в mysql. Одновременно около 20 подключений. Но спустя некоторое время падает, если увеличивается нагрузка то падает быстрее. Пишет что пул соединений переполнен. Соединения все закрываю. Использую .NET mysql connector в настройках мускула поставил 1000 одновременных подключений. Где настраивается пул и почему он переполняется?

Автор: mrbrooks 28.7.2010, 08:42
Цитата(kokcu @  25.7.2010,  18:56 Найти цитируемый пост)
Где настраивается пул

в строке подключения. можно его вообще отключить.
Цитата(kokcu @  25.7.2010,  18:56 Найти цитируемый пост)
почему он переполняется? 

видимо много подключений. причем с разных клиентов. 

я так понимаю закрытие соединения идет как аля MySqlConnection.Close(). При наличии пула соединений для закрытия соединения этого мало. Нужно также использовать статический метод MySqlConnection.ClearPool

Автор: kokcu 2.8.2010, 01:27
Нету такого метода(
Вообще какие есть опасные моменты при работе с базой данных? У меня локальное приложение и то при нагрузке падает иногда.

Автор: Springtime 2.8.2010, 06:50
Попробуй в строке подключения к базе, указать дополнительную опцию - Pooling=false
http://msdn.microsoft.com/en-us/library/8xx3tyca%28VS.71%29.aspx

Автор: mrbrooks 2.8.2010, 08:19
Цитата(kokcu @  2.8.2010,  02:27 Найти цитируемый пост)
Нету такого метода(

да ладно. 

ну тогда отключай пул соединений вообще как советует Springtime. Если не вкурсе как обзывается используй для подключения класс MySqlConnectionStringBuilder

Автор: kokcu 3.8.2010, 16:20
Поставил, но периодически выскакивает ошибка 
Код

object reference not set to an instance of an object


Программа просто обрабатывает одинаковые запросы.

Автор: Мурлыкатам_ 6.8.2010, 00:53
У меня таже проблема с пулом, чего я уже только не перепробывал с конекшен стрингом и какие ток настройки не делал.

Проблема тянется уже больше года smile

Возник логичный вопрос: А стоит ли постоянно создавать в юзинге SqlConnection и открывать его при каждом выполнение (у мя тоже по таймеру выполняется запрос один и тот же) или подключение можно просто сделать мембером класса и открывать его в конструкторе класса, а в методе который пишет, просто проверять на null и на ?

например:

Код

    class SqlWriter
    {
        private string _ConnectionString = string.Empty;
        private SqlConnection _Connection = null;
        private bool _QueryShouldStop = false;

        public SqlWriter(string connectionString)
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("connectionString");

            _ConnectionString = connectionString;

            if (_Connection == null)
                _Connection = new SqlConnection(_ConnectionString);

            if (_Connection.State != ConnectionState.Open)
                _Connection.Open();
        }

        public void StartQueryExecution(string query)
        {
            while (true)
            {
                if (_QueryShouldStop)
                {
                    if (_Connection != null)
                        if (_Connection.State == ConnectionState.Open)
                            _Connection.Close();

                    break;
                }
                
                if (_Connection == null)
                    _Connection = new SqlConnection(_ConnectionString);

                if (_Connection.State != ConnectionState.Open)
                    _Connection.Open();

                SqlCommand command = new SqlCommand(query, _Connection);

                try
                {
                    command.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex.ToString());
                }
            }
        }

        public void StopQueryExecution()
        {
            _QueryShouldStop = true;
        }
    }


В таком случае ведь не должно быть проблем с пулингом или в таком подходе есть какие-то другие подводные камни?

Посоветуйте пожалуйста, а то пулинг этот просто убивает. Раньше было по 100 соединений с базой все работало, никто ничего 
не менял, перестало работать. Самое обидное в пулинге - это его непредсказуемость. Хотя я понимаю, что проблемы с пулингом
может вызывать только утечка соединений.

Если кто имел опыт в борьбе с пулингом посредством настройки самого скл сервера, подскажите пожалуйста, где чего нужно настроить..

Спасибо.

Похожа моя проблема в незнании правил написания коннекшен стрингов smile

Автор: Мурлыкатам_ 6.8.2010, 02:58
Цитата(kokcu @ 2.8.2010,  01:27)
Нету такого метода(
Вообще какие есть опасные моменты при работе с базой данных? У меня локальное приложение и то при нагрузке падает иногда.

Метод очистки пула нужно вызывать у класса SqlConnection, а не у его объекта. Это статические методы.

Автор: mrbrooks 6.8.2010, 08:49
Цитата(Мурлыкатам_ @  6.8.2010,  01:53 Найти цитируемый пост)
А стоит ли постоянно создавать в юзинге SqlConnection и открывать его при каждом выполнение

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



Автор: kokcu 6.8.2010, 11:59
Спасибо, засунул claerpool и clearallpools в таймер посмотрим что получилось.
Я сейчас посмотрел process list на сервере и там этим подключений наверно тысяча. Так надо? 
Статус у все слип.

И еще одна странная вещь. Я завел счетчик активных соединений. Когда юзал open просто увеличивал его на 1, когда клоуз то уменьшал. 
Уменьшалки точно везде стоят, под каждым connection.Close() но почему то уже 700 активных подключений(((

Автор: mrbrooks 6.8.2010, 15:16
Цитата(kokcu @  6.8.2010,  12:59 Найти цитируемый пост)
Я завел счетчик активных соединений. Когда юзал open просто увеличивал его на 1, когда клоуз то уменьшал. 
Уменьшалки точно везде стоят, под каждым connection.Close() но почему то уже 700 активных подключений(((

покажи как сделал?

Автор: kokcu 6.8.2010, 21:16
Код

void mysqlq(string quer)
        {
            
                //Mysql Query function
                string MyConString = "SERVER=localhost;" +
                      "DATABASE=****;" +
                      "UID=****;" +
                      "PASSWORD=****;";
                MySqlConnection connection = new MySqlConnection(MyConString);
                
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader Reader;
                command.CommandText = quer;
                command.CommandTimeout = 0;
                connection.Open();
                active_connections++;
                try
                {
                    Reader = command.ExecuteReader();
                }
                catch
                {

                }
                connection.Close();
                active_connections--;
           
            GC.Collect();
        }

Всем спасибо но вроде проблема решилась командой SET GLOBAL wait_timeout = 100;
Спящие тысячи запросов уходят сами.  5 часов аптайма и все ок)

Автор: kokcu 6.8.2010, 23:30
теперь другая проблема((( программа начинает примерно через 6 часов жутко тормозить и жрать половину проца и 100м оперативы( что делать?

Автор: mrbrooks 9.8.2010, 09:11
тут сложно что либо сказать. юзай профайлер, что бы выявить данные утечки.

Автор: Springtime 9.8.2010, 14:32
Цитата(mrbrooks @ 6.8.2010,  15:16)
Цитата(kokcu @  6.8.2010,  12:59 Найти цитируемый пост)
под каждым connection.Close() но почему то уже 700 активных подключений(((

тебе уже написали, что следует выключить пул соединений
я с таким же сталкивался только у нас сервак на котором MS SQL просто напросто зависал эпизодически раз в 2 месяца.

Автор: Мурлыкатам_ 10.8.2010, 07:59
Цитата(Springtime @ 9.8.2010,  14:32)
Цитата(mrbrooks @ 6.8.2010,  15:16)
Цитата(kokcu @  6.8.2010,  12:59 Найти цитируемый пост)
под каждым connection.Close() но почему то уже 700 активных подключений(((

тебе уже написали, что следует выключить пул соединений
я с таким же сталкивался только у нас сервак на котором MS SQL просто напросто зависал эпизодически раз в 2 месяца.

А может из-за включенного пула соединений MS SQL начать педалить рандомно? У мя минут 5 работает оки доки, потом бац - 100% проца и подвисает секунд на 20.

Добавлено через 5 минут и 29 секунд
Цитата(kokcu @ 6.8.2010,  23:30)
теперь другая проблема((( программа начинает примерно через 6 часов жутко тормозить и жрать половину проца и 100м оперативы( что делать?

А может просто дофига в базе данных накапливается и комп не справляется?

А ты пробывал заюзать CommandBehavior.CloseConnection и закрытие ридера:

Код

 SqlDataReader reader = null;

                try
                {
                    reader = command.ExecuteReader(CommandBehavior.CloseConnection);

                    //use reader

                    reader.Close();

                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex.ToString());
                }


Если попробуешь, отпишись плз о результатах.

Добавлено через 8 минут и 5 секунд
Цитата(kokcu @ 6.8.2010,  21:16)
Код

void mysqlq(string quer)
        {
            
                //Mysql Query function
                string MyConString = "SERVER=localhost;" +
                      "DATABASE=****;" +
                      "UID=****;" +
                      "PASSWORD=****;";
                MySqlConnection connection = new MySqlConnection(MyConString);
                
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader Reader;
                command.CommandText = quer;
                command.CommandTimeout = 0;
                connection.Open();
                active_connections++;
                try
                {
                    Reader = command.ExecuteReader();
                }
                catch
                {

                }
                connection.Close();
                active_connections--;
           
            GC.Collect();
        }

Всем спасибо но вроде проблема решилась командой SET GLOBAL wait_timeout = 100;
Спящие тысячи запросов уходят сами.  5 часов аптайма и все ок)

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

Автор: Springtime 11.8.2010, 12:19
Цитата(Мурлыкатам_ @  10.8.2010,  07:59 Найти цитируемый пост)
А может из-за включенного пула соединений MS SQL начать педалить рандомно?

Не совсем понял )))

Автор: Мурлыкатам_ 13.8.2010, 16:35
Цитата(Springtime @ 11.8.2010,  12:19)
Цитата(Мурлыкатам_ @  10.8.2010,  07:59 Найти цитируемый пост)
А может из-за включенного пула соединений MS SQL начать педалить рандомно?

Не совсем понял )))

При включенном пулинге соединений MS SQL Server 2005 может начать педалить в рандомное время?

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

Самый главный и волнующий лично меня вопрос:
- Рационально, разумно, логично ли сделать SqlConnection мембер полем класса, который пишет в базу и открывать его в конструкторе класса,
а затем в каждом методе просто проверять на налл и на закрытое состояние (и открывать по необходимости если оно было закрыто неожиданно). В этом случае, не нужно в каждом методе делать:
1 Создавать экземпляр класса
Код

SqlConnection connection = new SqlConnection(_DbConnectionString);


2 Открывать и закрывать соединение при выполнение каждой комманды (допустим прилада выполняет 1000 запросов  к базе в час, так зачем нам 1000 раз создавать экземпляр класса скл соединение и 1000 раз открывать/закрывать его, на мой взгляд - это очевидное расточительство производительности).

Очень буду рад если кто нить аргументировано скажет, можно так делать или не стоит так делать и почему.

Спасибо.

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

Автор: Springtime 13.8.2010, 20:24
Цитата(Мурлыкатам_ @  13.8.2010,  16:35 Найти цитируемый пост)
Рационально, разумно, логично ли сделать SqlConnection мембер полем класса, который пишет в базу и открывать его в конструкторе класса

Так у тебя же запрос будет производиться в методе? если я правильно понял, вот там открывай и закрывай сразу
а так я бы сделал статический метод в классе
где в самом классе идёт его настройка на этапе компиляции, а при вызове метода соответственно подключение и отключение к базе
без создания множества раз экземпляра класса
если я тебя правильно понял

а так по существу, множество раз делать -
Код

SqlConnection connection = new SqlConnection(_DbConnectionString);

это норма, по сути ADO.NET для этого и делался

Автор: kokcu 13.8.2010, 23:31
Вот так нужно?
Код

void mysqlq(string quer)
        {
                //Mysql Query function
                string MyConString = "SERVER=localhost;" +
                      "DATABASE=gpsm;" +
                      "UID=root;" +
                      "PASSWORD=1;";
                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();
                    MySqlDataReader Reader;
                    command.CommandText = quer;
                    command.CommandTimeout = 0;
                    connection.Open();
                    active_connections++;
                    try
                    {
                        Reader = command.ExecuteReader(CommandBehavior.CloseConnection);
                        
                        Reader.Close();
                    }
                    catch
                    {
                       
                    }
                    connection.Close();
                    active_connections--;
 
А пул нужно в таком случае отключать? 
Код

string MyConString = "SERVER=localhost;" +
                      "DATABASE=gpsm;" +
                      "UID=root;" +
                      "Pooling = false;"+
                      "PASSWORD=1;";

Здесь часто мелькает mssql, я с mysql работаю, или разницы нет?
Цитата

А может просто дофига в базе данных накапливается и комп не справляется?

Выполняются восновном update запросы. Добавляется редко. А нагрузка примерно 2-5 команд в секунду.

Автор: mrbrooks 16.8.2010, 07:58
Цитата(kokcu @  14.8.2010,  00:31 Найти цитируемый пост)
Вот так нужно?

не совсем. либо используй command.ExecuteReader в блоке using, либо закрывай Reader в finally. зачем тебе здесь Reader не ясно, полагаю  код опустил.

и зачем повторно закрываешь соединение (command.ExecuteReade(CommandBehavior.CloseConnection) & connection.Close())?
хотя это не смертельно.

Цитата(kokcu @  14.8.2010,  00:31 Найти цитируемый пост)
А пул нужно в таком случае отключать? 

типа того.

Цитата(kokcu @  14.8.2010,  00:31 Найти цитируемый пост)
Здесь часто мелькает mssql, я с mysql работаю, или разницы нет?

это как посмотреть.

Автор: kokcu 16.8.2010, 14:29
Отписываюсь о результатах.
Код

pooling = false;

Привело к падению программы без ошибок через 10 минут, и так несколько раз(
Код

max_pool_size = 3000;

Попробую так, главное чтоб проработало сутки. Ошибку исправил с закрытием ридера.
А нужно Dispose вызывать? Или Close достаточно?

Автор: mrbrooks 17.8.2010, 07:48
Цитата(kokcu @  16.8.2010,  15:29 Найти цитируемый пост)
А нужно Dispose вызывать? Или Close достаточно?

само по себе без разницы. но если есть Close - то его. Типа читаемость лучше и блаблабла.

Цитата(kokcu @  16.8.2010,  15:29 Найти цитируемый пост)
Отписываюсь о результатах.

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

Автор: kokcu 18.8.2010, 14:43
Кстате раз в минуту по таймеру делается Очистка всех пулов.
Но висеть sleep все равно остаются

Автор: whoever 30.8.2010, 21:07
Вполне возможно, что пул переполняется из-за незакрытых соединений в результате ошибок. Вы же не вызываете Dispose или Close гарантированно (Dispose в случае с SqlConnection [подозреваю, что и с MySqlConnection] делает то же самое, что и Close). Используйте using, либо делайте класс (в который оборачиваете подключение и непосредственную работу с базой) IDisposable, в методе Dispose которого проверяйте, закрыто ли подключение, и если нет, то закрывайте, а сам класс используйте вкупе с using.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)