Подтвердить что ты не робот

Как обращаться к MySQL из нескольких потоков одновременно

Мы делаем небольшой тест MySQL, где хотим видеть, как он работает для наших данных.

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

Документация по MySQL (5.0) не совсем понятна для многопоточных клиентов. Я должен указать, что я связываюсь с библиотекой, защищенной потоком (libmysqlclient_r.so)

Я использую подготовленные инструкции и читаю (SELECT) и записываю (UPDATE, INSERT, DELETE).

  • Должен ли я открыть одно соединение на поток? И если да: как это сделать... кажется, что mysql_real_connect() возвращает исходный дескриптор БД, который я получил, когда вызывал mysql_init())
  • Если нет: как я могу убедиться, что результаты и методы, такие как mysql_affected_rows, возвращают правильное значение вместо того, чтобы сталкиваться с другими потоковыми вызовами (mutex/locks могут работать, но он чувствует себя не так).
4b9b3361

Ответ 1

Как поддерживающий довольно большое приложение C, которое делает запросы MySQL из нескольких потоков, я могу сказать, что у меня не было проблем с простое создание нового соединения в каждом потоке. Некоторые оговорки, которые я встретил:

  • Изменить: похоже, эта пуля применима только к версиям < 5,5; см. эту страницу для вашей соответствующей версии: Как вы уже сказали, ссылку на libmysqlclient_r.
  • Вызовите mysql_library_init() (один раз, от main()). Прочтите документы об использовании в многопоточных средах, чтобы узнать, почему это необходимо.
  • Создайте новую структуру MYSQL, используя mysql_init() в каждом потоке. У этого есть побочный эффект вызова mysql_thread_init() для вас. mysql_real_connect(), как обычно, внутри каждого потока, с его структурой MYSQL, специфичной для потока.
  • Если вы создаете/уничтожаете много потоков, вы захотите использовать mysql_thread_end() в конце каждого потока (и mysql_library_end() в конце main()). В любом случае, это хорошая практика.

В принципе, не разделяйте структуры MYSQL или что-либо, созданное специально для этой структуры (т.е. MYSQL_STMT s), и оно будет работать так, как вы ожидаете.

Это похоже на работу меньше, чем создание пула соединений.

Ответ 2

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

Здесь есть статья описывающая про и минусы пула соединений (хотя он основан на Java)

Изменить: здесь SO-вопрос/ответ о пулах соединений в C

Edit2: Здесь ссылка на образец Пул соединений для MySQL, написанный на С++. (вы, вероятно, должны игнорировать утверждения goto, когда вы реализуете свои собственные.)

Ответ 3

Мне кажется, что из mySQL Docs любая структура MYSQL может быть использована в потоке без труда - использование одной и той же структуры MYSQL в разных потоках одновременно явно даст вам крайне непредсказуемые результаты, поскольку состояние хранится в MYSQL соединение.

Таким образом, либо создайте соединение для каждого потока, либо используйте пул соединений, как было предложено выше, и защитите доступ к этому пулу (т.е. резервирование или освобождение соединения) с использованием какого-либо Mutex.

Ответ 4

MySQL Threaded Clients в C

В нем указано, что mysql_real_connect() по умолчанию не является потокобезопасным. Библиотеку клиента необходимо скомпилировать для поточного доступа.