Spec-Zone.ru › MySQL Connectors 1.0

3.4 Создание многопоточных клиентских программ API C

Этот раздел содержит рекомендации по написанию клиентских программ, использующих функции, связанные с потоками, в MySQL C API. Дополнительную информацию об этих функциях см. в разделе 8.2 «Описание функций C API с поддержкой потоков». Примеры исходного кода, использующего эти функции, можно найти в каталоге client дистрибутива исходного кода MySQL:

  • Исходный код программы mysqlimport использует потоки в коде, связанном с опцией.

  • Исходный код программы mysqlslap использует потоки для создания одновременных рабочих нагрузок, чтобы протестировать работу сервера при высокой нагрузке.

В качестве альтернативы программированию потоков приложения могут найти полезными асинхронные (бесблокирующие) функции C API. Эти функции позволяют приложениям отправлять несколько незавершенных запросов на сервер и определять, когда каждый из них завершится, с помощью опроса. Дополнительную информацию см. в главе 7 «Асинхронный интерфейс C API».

Если при линковке многопоточной программы с библиотекой MySQL клиента возникают ошибки undefined-reference, наиболее вероятной причиной является то, что вы не включили библиотеки потоков в команду компиляции/линковки.

Библиотека клиента почти потокобезопасна. Основная проблема заключается в том, что подпрограммы в sql/net_serv.cc, которые читают из сокетов, не безопасны для прерываний. Это было сделано с мыслью о том, что вы можете иметь свой собственный механизм прерывания, который может прервать длительное чтение на сервер. Если вы установите обработчики прерываний для прерываний SIGPIPE, обработка сокетов должна стать потокобезопасной.

Чтобы избежать аварийного завершения программы при завершении соединения, MySQL блокирует SIGPIPE при первом вызове mysql_library_init(), mysql_init() или mysql_connect(). Чтобы использовать свой собственный SIGPIPE обработчик, сначала вызовите mysql_library_init(), а затем установите ваш обработчик.

Библиотека клиента потокобезопасна на уровне подключения. Два потока могут совместно использовать одно подключение с указанными ниже оговорками:

  • Если вы не используете асинхронные функции C API, упомянутые ранее, несколько потоков не могут отправлять запрос на MySQL-сервер одновременно по одному подключению. В частности, вы должны гарантировать, что между вызовами mysql_real_query() (или mysql_query()) и mysql_store_result() в одном потоке, другой поток не использует то же самое подключение. Для этого используйте блокировку мьютекса вокруг вашей пары вызовов mysql_real_query() (или mysql_query()) и mysql_store_result(). После того, как mysql_store_result() вернёт значение, блокировка может быть освобождена, и другие потоки могут запросить это же подключение.

    Если вы используете POSIX-потоки, вы можете использовать pthread_mutex_lock() и pthread_mutex_unlock() для создания и освобождения блокировки мьютекса.

    Примечание

    Если вы изучаете программы в дистрибутиве исходного кода MySQL, вместо вызовов pthread_mutex_lock() и pthread_mutex_unlock() вы увидите вызовы native_mutex_lock() и native_mutex_unlock(). Последние функции определены в заголовочном файле thr_mutex.h и соответствуют платформам функций мьютекса.

  • Несколько потоков могут получать доступ к различным наборам результатов, полученным с помощью mysql_store_result().

  • Чтобы использовать mysql_use_result(), вы должны убедиться, что ни один другой поток не использует то же самое подключение до закрытия набора результатов. Однако, в многопоточных клиентах, которые совместно используют одно подключение, лучше использовать mysql_store_result().

Если поток не создает подключение к базе данных MySQL, но вызывает функции MySQL, учтите следующее:

При вызове mysql_init(), MySQL создаёт поток-специфическую переменную для потока, которая используется библиотекой отладки (и не только). Если вы вызываете функцию MySQL до того, как поток вызовет mysql_init(), у потока нет необходимых поток-специфических переменных, и рано или поздно может произойти сбой ядра. Чтобы избежать проблем, необходимо выполнить следующее:

  1. Вызовите mysql_library_init() перед любыми другими функциями MySQL. Она не потокобезопасна, поэтому вызовите её до создания потоков или защитите вызов мьютексом.

  2. Убедитесь, что mysql_thread_init() вызывается в начале обработчика потока перед вызовом любой функции MySQL. (Если вы вызываете mysql_init(), он вызывает mysql_thread_init() за вас.)

  3. В потоке вызовите mysql_thread_end() перед вызовом pthread_exit(). Это освободит память, используемую потокоспецифическими переменными MySQL.

Предыдущие замечания относительно mysql_init() также относятся к mysql_connect(), которая вызывает mysql_init().

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/c-api-8.0-en/c-api-threaded-clients.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API