Я пишу многопоточную объектно-ориентированную программу на C#, которая работает с MSSQL2005. При этом различные классы реализуют функционал доступа к базе данных — интерфейс класса ориентирован на логику работы программы, а в реализации методов и свойств "зашита" логика работы с базой данных.
При этом часто возникают ситуации, когда требуется одновременное выполнение множества SQL-запросов из разных потоков.
Вопрос состоит в следующем — как в этом случае лучше организовать соединение с базой данных (SqlConnection) в такой многопоточной среде? Я вижу два варианта:
(1) сложный: иметь столько соединений, сколько запущено потоков, и в каждом потоке использовать свое соединение. Реализовать это можно, например, с помощью глобального объекта Dictionary<int, SqlConnection>, где ключом будет ID обращающегося потока, и класса-оболочки DataBaseConnection, статическое свойство Connection которого будет проверять, есть ли в словаре соединение для текущего потока и, если нет — то создавать его. Идея кажется интересной, но возникают накладные расходы, связанные с обращением к свойству, поиску в словаре, плюс надо как-то отслеживать завершение работы потоков и закрывать соответствующие соединения
(2) простой: перед выполнением любого запроса (или набора запросов, которые гарантированно выполняются в одном потоке) создавать новое соединение с БД, а потом закрывать его?
Хочу узнать ваше мнение — какой метод лучше?
велики ли накладные расходы на создание соединения (запросов довольно много)? Как можно недорого отследить завершение/создание потока в первом способе (кроме проверки словаря)?
Re: Многопоточность: одновременное выполнение многих запрос
Здравствуйте, Kimus, Вы писали:
K>Вопрос состоит в следующем — как в этом случае лучше организовать соединение с базой данных (SqlConnection) в такой многопоточной среде? Я вижу два варианта:
K>(1) сложный: иметь столько соединений, сколько запущено потоков, и в каждом потоке использовать свое соединение. Реализовать это можно, например, с помощью глобального объекта Dictionary<int, SqlConnection>, где ключом будет ID обращающегося потока, и класса-оболочки DataBaseConnection, статическое свойство Connection которого будет проверять, есть ли в словаре соединение для текущего потока и, если нет — то создавать его. Идея кажется интересной, но возникают накладные расходы, связанные с обращением к свойству, поиску в словаре, плюс надо как-то отслеживать завершение работы потоков и закрывать соответствующие соединения
а стандартный пул соединений уже не подходит?
Re[2]: Многопоточность: одновременное выполнение многих зап
Здравствуйте, Svjat, Вы писали:
S>а стандартный пул соединений уже не подходит?
Я не знал, что они существуют. Сейчас почитал о нем, узнал. Спасибо.
Пробую такой тест:
str = @"Data Source=(local)\SQLEXPRESS;Initial Catalog=mq6;Integrated Security=True;";
for (int i = 0; i < 10000; i++)
{
using (SqlConnection s = new SqlConnection(str))
{
s.Open();
s.Close();
}
занимает 4 секунды.
если строку заменить на
str = @"Data Source=(local)\SQLEXPRESS;Initial Catalog=mq6;Integrated Security=True;Connection Lifetime=1000;Pooling=true;Max Pool Size=80;Min Pool Size=10;";
то занимает тоже 4 секунды.
это
(1) у меня ничего не работает?
или
(2) пул есть в любом случае, поэтому явная его настройка не чувствуется?
если (1) то что не правильно?
Re: Многопоточность: одновременное выполнение многих запрос
Здравствуйте, Kimus, Вы писали:
K>(2) простой: перед выполнением любого запроса (или набора запросов, которые гарантированно выполняются в одном потоке) создавать новое соединение с БД, а потом закрывать его?
Именно так. Здесь в игру вступает Connection Pool.
Re[2]: Многопоточность: одновременное выполнение многих зап
Здравствуйте, Svjat, Вы писали:
S>Здравствуйте, Kimus, Вы писали:
K>>Вопрос состоит в следующем — как в этом случае лучше организовать соединение с базой данных (SqlConnection) в такой многопоточной среде? Я вижу два варианта:
K>>(1) сложный: иметь столько соединений, сколько запущено потоков, и в каждом потоке использовать свое соединение. Реализовать
S>а стандартный пул соединений уже не подходит?
А что, до варианта (2) в исходном сообщении ты недошел?
Re: Многопоточность: одновременное выполнение многих запрос
Здравствуйте, Kimus, Вы писали:
K>это K>(1) у меня ничего не работает? K>или K>(2) пул есть в любом случае, поэтому явная его настройка не чувствуется?
Пул по умолчанию создается, если явно не указано Pooling=false
Re[3]: Многопоточность: одновременное выполнение многих зап
Здравствуйте, _d_m_, Вы писали:
K>>>(1) сложный: иметь столько соединений, сколько запущено потоков, и в каждом потоке использовать свое соединение. Реализовать
S>>а стандартный пул соединений уже не подходит?
___>А что, до варианта (2) в исходном сообщении ты недошел?
дошел, просто второй вариант был про накладные расходы при реальном open/close.
а прочитав про пул автор и так все сам понял.
согласен, что можно было сразу подробнее ответить, замечание принято
но вобщем в ветке уже все сказали.
Re[2]: Многопоточность: одновременное выполнение многих зап
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, Kimus, Вы писали:
K>>(2) простой: перед выполнением любого запроса (или набора запросов, которые гарантированно выполняются в одном потоке) создавать новое соединение с БД, а потом закрывать его?
___>Именно так. Здесь в игру вступает Connection Pool.
все так, но вот беда — если пользоваться пулом не зная о его существовании, можно легко "попасть"
много раз видел, когда девелоперы начиная работать с бд
копипейстят из примеров конекшн стринг вместе с "pooling=false" не понимая зачем это.