Многопоточное использование MySqlConnection

194
24 февраля 2018, 18:53

В приложении необходимо использовать постоянно подключение к MySQL Серверу. Подключения производятся из разных потоков с разной интенсивностью.

Изучив немного вопрос использования Connector/NET написал следующий код:

public sealed class DatabaseManager
{
    private static Logger _log = new Logger("DatabaseManager");
    private static volatile DatabaseManager INSTANCE;
    private static object syncRoot = new Object();
    private static MySqlConnection _connection;
    private static string host = "192.168.1.100";
    private static string database = "test";
    private static string user = "root";
    private static string password = "2223322";
    private static string _connectionString = "Data Source=" + host + ";Database=" + database + ";User ID=" + user + ";Password=" + password + ";Character Set=utf8";
    private DatabaseManager()
    {
        // Do nothing.
    }
    public void init()
    {
        _connection = new MySqlConnection(_connectionString);
        try
        {
            _connection.Open();
            using (MySqlCommand command = _connection.CreateCommand())
            {
                command.CommandText = "CREATE TABLE IF NOT EXISTS connection_test_table (`a` char(1) DEFAULT NULL)";
                command.ExecuteNonQuery();
            }
            _connection.Close();
            _log.info("Database connection activated successful.");
        }
        catch (Exception e)
        {
            _log.error("Attempting to connect to: " + database + "@" + host + "...", e.Message, e.StackTrace);
        }
    }
    public void shutdown()
    {
        try
        {
            _connection.Close();
        }
        catch (Exception e)
        {
            _log.error("Error while closing Database connection.", e.Message, e.StackTrace);
        }
        try
        {
            _connection = null;
        }
        catch (Exception e)
        {
            _log.error("Errur while destroing connection object.", e.Message, e.StackTrace);
        }
    }
    public MySqlConnection getConnection()
    {
        while (_connection == null)
        {
            if (_connection == null)
            {
                _connection = new MySqlConnection(_connectionString);
                _connection.Open();
            }
        }
        if (_connection.State != ConnectionState.Open)
            _connection.Open();
        return _connection;
    }
    public static DatabaseManager getInstance
    {
        get
        {
            if (INSTANCE == null)
            {
                lock (syncRoot)
                {
                    if (INSTANCE == null)
                        INSTANCE = new DatabaseManager();
                }
            }
            return INSTANCE;
        }
    }
}

Данный Singleton использую следующим образом (тестовый пример воткнул в таймер формы):

using (MySqlCommand command = DatabaseManager.getInstance.getConnection().CreateCommand())
{
    command.CommandText = "TRUNCATE TABLE connection_test_table";
    command.ExecuteNonQuery();
}

При закрытии приложения использую вызов метода:

DatabaseManager.getInstance.shutdown();

Лог времени выполнения запросов (с учётом что MySQL сервер находится на другом ПК в локальной сети):

23.02.2018, 19:44:32 [INFO]: Database connection activated successful. 
23.02.2018, 19:44:32 [INFO]: Timestamp: Elapsed Time -> 0.410 sec. 
23.02.2018, 19:44:33 [INFO]: Timestamp: Elapsed Time -> 0.028 sec. 
23.02.2018, 19:44:34 [INFO]: Timestamp: Elapsed Time -> 0.018 sec. 
23.02.2018, 19:44:35 [INFO]: Timestamp: Elapsed Time -> 0.011 sec. 
23.02.2018, 19:44:36 [INFO]: Timestamp: Elapsed Time -> 0.024 sec. 
23.02.2018, 19:44:37 [INFO]: Timestamp: Elapsed Time -> 0.019 sec. 
23.02.2018, 19:44:38 [INFO]: Timestamp: Elapsed Time -> 0.010 sec. 
23.02.2018, 19:44:39 [INFO]: Timestamp: Elapsed Time -> 0.063 sec. 
23.02.2018, 19:44:40 [INFO]: Timestamp: Elapsed Time -> 0.040 sec.

Само создание подключения занимает около полсекунды. Время всех остальных запросов эквивалентно времени запросов из Navicat.

Так вот теперь сами вопросы:

  1. Насколько корректно создана модель подключения к БД для многопоточного приложения?
  2. Будет ли использоваться пул соединений или оно получается единственное в пуле?

P.S. Извиняюсь за профанство, но в Java, к примеру, используется не только Connector/J коннектор, но и пул менеджер, коих целый зоопарк. Самые распространённые: c3p0, HikariCP, BoneCP. И после создания подключения оно вызывается из пул менеджера.

READ ALSO
System.OutOfMemoryException: “Недостаточно памяти.”

System.OutOfMemoryException: “Недостаточно памяти.”

Как решается подобное исключение ?

166
C#. Обработка нажатия inline и reply кнопок для бота telegram

C#. Обработка нажатия inline и reply кнопок для бота telegram

Для создания telegram-бота использую package TelegramBot

970
Как узнать текущее значение suspendState?

Как узнать текущее значение suspendState?

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

188
Управление Serial Port rs485 - протокол modbus rtu

Управление Serial Port rs485 - протокол modbus rtu

Появилась необходимость написать приложение которое может общаться с некоторым устройством, оно имеет интерфейс rs485 работает по протоколу...

192