3.4 编写 C API 线程客户端程序

本节为编写使用 MySQL C API 中线程相关函数的客户端程序提供指导。有关这些函数的更多信息,请参阅 第 8.2 节,“C API 线程函数说明”。有关使用它们的源代码示例,请查看 clientMySQL 源代码分发目录:

  • mysqlimport 的源代码在与该--use-threads选项 关联的代码中使用线程 。

  • mysqlslap 的源代码使用线程来设置并发工作负载,以测试高负载下的服务器操作。

作为线程编程的替代方案,应用程序可能会发现异步(非阻塞)C API 函数很有用。这些功能使应用程序能够向服务器提交多个未完成的请求,并确定每个请求何时完成使用轮询。有关详细信息,请参阅 第 7 章,C API 异步接口

如果在将线程程序链接到 MySQL 客户端库时发生未定义引用错误,最可能的原因是您没有在链接/编译命令中包含线程库。

客户端库几乎是线程安全的。最大的问题是sql/net_serv.cc从套接字读取的子程序不是中断安全的。这样做的想法是,您可能希望拥有自己的警报来中断对服务器的长时间读取。如果为 SIGPIPE中断安装中断处理程序,套接字处理应该是线程安全的。

为避免在连接终止时中止程序,MySQLSIGPIPE在第一次调用 mysql_library_init()mysql_init()或 时阻塞mysql_connect()。要使用您自己的 SIGPIPE处理程序,请先调用 mysql_library_init(),然后安装您的处理程序。

客户端库对每个连接都是线程安全的。两个线程可以共享相同的连接,但需要注意以下几点:

  • 除非您使用前面提到的异步 C API 函数,否则多个线程不能在同一连接上同时向 MySQL 服务器发送查询。特别是,您必须确保在对 mysql_real_query()(or mysql_query()) 的调用之间和 mysql_store_result()在一个线程中,没有其他线程使用相同的连接。为此,请在您的 mysql_real_query()(or mysql_query()) 和 mysql_store_result()调用对周围使用互斥锁。返回后mysql_store_result() ,可以释放锁,其他线程可以查询同一个连接。

    如果使用 POSIX 线程,则可以使用 pthread_mutex_lock()and pthread_mutex_unlock()来建立和释放互斥锁。

    笔记

    如果您检查 MySQL 源代码分发中的程序,您将看到对and 的调用,而不是对pthread_mutex_lock() and的调用。后面的函数在 头文件中定义并映射到特定于平台的互斥函数。 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 函数之前安排 mysql_thread_init()在线程处理程序中提前调用。(如果你打电话 mysql_init(),它会打电话 mysql_thread_init()给你。)

  3. 在线程中,先调用 mysql_thread_end()再调用pthread_exit()。这释放了 MySQL 线程特定变量使用的内存。

前面的注意事项 mysql_init()也适用于 mysql_connect()调用 mysql_init().