Нужна помощь в управлении соединениями MySql
У меня проблемы с поиском четкого объяснения пула подключений. Я создаю приложение с использованием коннектора.NET, который я скачал с mysql.com. Приложению требуется только одно соединение с БД, но оно будет работать одновременно примерно на 6 машинах в моей сети. Обычно я создаю соединение при запуске и просто оставляю его. Но я вижу много сообщений от людей, которые говорят, что это плохая практика. Также меня беспокоит время ожидания. Мое приложение будет работать 24 часа в сутки, 7 дней в неделю и без активности базы данных.
Я склоняюсь к следующему:
using (MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
// use connection
}
Но я не уверен, что понимаю, что происходит на заднем плане. Действительно ли это закрывает соединение и позволяет gc уничтожить объект, или есть встроенное поведение пула, которое сохраняет объект и повторно доставляет его в следующий раз, когда я пытаюсь его создать?
Я, конечно, не хочу, чтобы приложение повторно аутентифицировалось в сети каждый раз, когда я обращаюсь к базе данных.
Может кто-нибудь предложить мне совет?
3 ответа
Обычно в этом случае провайдеры.net используют пулы соединений.
Соединение должно просто вернуться в пул в конце вашего использования.
Я не заглядывал в ловушку с MySQL профилировщиком, но у меня есть код, который зависит от него - у меня не было проблем с этим.
Обновление: я только что посмотрел на вызовы, сделанные во время утилизации, и он определенно выполняет пул соединений, то есть в итоге вызывает:
internal void CloseFully()
{
if (this.settings.Pooling && this.driver.IsOpen)
{
if ((this.driver.ServerStatus & ServerStatusFlags.InTransaction) != 0)
{
new MySqlTransaction(this, IsolationLevel.Unspecified).Rollback();
}
MySqlPoolManager.ReleaseConnection(this.driver);
}
else
{
this.driver.Close();
}
this.driver = null;
}
Обновление 2 / ответ на комментарий: экземпляр MySqlConnection отличается от другого, так как оператор using имеет дело только с утилизацией (освобождением ресурсов). Из-за этого вам не нужно проверять, закрыто ли оно. MySqlConnection внутренне использует другие классы / экземпляры, то есть, если он захватывает соответствующий экземпляр. Это прозрачно для вашего кода, поэтому вы используете его так же, как если бы это было новое + другое соединение / как в коде, который вы опубликовали.
Как вы сказали, чтобы иметь возможность повторно использовать соединение более низкого уровня (называемое драйвером в коде соединителя mysql), каждый пул определяется строкой соединения.
Согласно этому сообщению, соединения сохраняются и объединяются по умолчанию в течение 60 секунд, а затем закрываются.
Отключенная модель является наиболее используемой во всем мире, хотя она не злоупотребляет аутентификацией снова и снова.
Отключенный режим
Вот некоторые причины, по которым вы хотите работать отключенные большую часть времени:
- Количество CLA (клиентских лицензионных соглашений), купленных для вашего сервера базы данных (ну, в действительности, здесь не применимо, поскольку это MySQL);
- Если одновременно подключено слишком много людей, это замедляет DBE (компонент Database Engine);
- Сохранение открытых соединений делает сеть занятой, а слишком загруженная сеть с большей вероятностью выйдет из строя;
- Пока пользователь редактирует, скажем, данные клиента, ему не нужно сохранять соединение с сервером базы данных и, возможно, блокировать строку или таблицу данных, что может привести к большим проблемам с одновременной блокировкой.
Этот код:
using(MySqlConnection conn = new MySqlConnection(connStr)) {
if (conn.State == ConnectionState.Closed)
try {
conn.Open();
} catch (MySqlException ex) {
// Exception handling here...
}
// Use of connection here...
}
Ключевое слово using используется для автоматического удаления объектов, созданных в нем, в соответствии со ссылкой на статью:
Определяет область, за пределами которой объект или объекты будут расположены.
Таким образом, вы гарантируете, что если соединение больше не требуется, вы избавляетесь от него. Так что да, новая аутентификация потребуется после повторного создания этого соединения, поскольку оно больше не существует. В течение короткого времени здесь проводится небольшой опрос, но вам не о чем беспокоиться.
Подключенный режим
Чтобы обеспечить использование только одного такого соединения во всем приложении, вы должны использовать его как одиночный. Однако, как только ваша строка подключения изменится, однажды вам нужно будет убедиться, что все приложение закрывается и снова открывается, так что это соединение получает обновленную строку соединения. Это нежизнеспособно, но я не знаю вашего контекста.
Использование блока приложения доступа к данным Enterprise Library
Для того, чтобы ваш пул соединений был управляемым, вы можете использовать блок приложения доступа к данным Enterprise Library.
DAAB - это простой в использовании, полностью настраиваемый уровень доступа к данным, разработанный инженерами Microsoft и другими участвующими компаниями. Тогда управление пулом соединений может быть простым как 1-2-3!
Я думаю, что вы могли бы многого добиться, используя DAAB, который полностью настраивается в XML-файле и требует очень низких эксплуатационных расходов.
РЕДАКТИРОВАТЬ Если бы я мог продвинуться немного дальше, я бы, возможно, подумал об использовании шаблона проектирования Фасад с Фабриками.
Эффективное использование шаблона проектирования фасадов и фабрик
Обладая "умным" фасадом, именно он обеспечивает вам необходимую связь. Таким образом, вот простой пример (при условии, что у вас есть настройка проекта с именем "DefaultConnectionString"):
public static class ApplicationFacade {
private static readonly ApplicationFactory _applicationFactory = new ApplicationFactory();
public static DefaultConnectionString {
get {
return Properties.Settings.Default.DefaultConnectionString;
}
}
public static IList<ICustomer> GetCustomers() {
using(var connection = OpenConnection())
_applicationFactory.GetCustomers(connection);
}
public MySqlConnection OpenConnection() {
var newConnection = new MySqlConnection(DefaultConnectionString);
try {
newConnection.Open();
} catch (Exception ex) {
// Exception handling...
}
return newConnection;
}
}
internal sealed class ApplicationFactory {
internal ApplicationFactory() {
}
internal IList<ICustomer> GetCustomers(MySqlConnection connection) {
if (connection.State != ConnectionState.Open)
throw new InvalidOperationException()
IList<ICustomer> customers = new List<ICustomer>();
var command = new MySqlCommand(connection, @"select * from Customers");
// Place code to get customers here...
return customers;
}
}
// So you'll be able to use share the same connection throught your factory whenever needed, preventing the overkill of authentication over and over again. Here's how this would be used:
public partial class MainForm : Form {
private void PopulateGrid() {
dataGridView1.DataSource = ApplicationFacade.GetCustomers();
// And you never care about the connection! All you want is the list of customers, that's all!
}
}
Это шаблон, который я часто использую в своих проектах разработки. Это позволяет использовать единую точку входа в мои библиотеки классов, и они очень просты в использовании.
Ну, возможно, это больше, чем вы просили, но я надеюсь, что это поможет.