我们正在做一个小型的MySQL基准测试,我们想看看它对我们的数据的执行情况。
该测试的一部分是看多个并发线程在服务器上进行各种查询时它是如何工作的。
MySQL documentation(5.0)对多线程客户端并不十分清楚。我应该指出,我确实链接了线程安全库(libmysqlclient_r.so
)
我正在使用预准备语句并执行read(SELECT)和write(UPDATE,INSERT,DELETE)。
mysql_real_connect()
返回我在调用mysql_init()
时获得的原始数据库句柄mysql_affected_rows
之类的结果和方法返回正确的值而不是与其他线程的调用冲突(互斥/锁可能有效,但感觉不对)答案 0 :(得分:26)
作为一个从多个线程调用MySQL的相当大的C应用程序的维护者,我可以说我只是在每个线程中创建一个新连接没有问题。我遇到的一些警告:
libmysqlclient_r
相关联。mysql_library_init()
(一次,来自main()
)。阅读有关在多线程环境中使用的文档,了解为什么有必要。mysql_init()
创建一个新的MYSQL
结构。这会产生为您调用mysql_thread_init()
的副作用。像往常一样mysql_real_connect()
在每个线程内部,使用其特定于线程的MYSQL结构。mysql_thread_end()
(并在main()
末尾使用mysql_library_end()
)。无论如何,这是很好的做法。基本上,不要共享MYSQL
结构或任何特定于该结构创建的结构(即MYSQL_STMT
s),它将按预期工作。
这似乎比向我建立连接池要少。
答案 1 :(得分:6)
您可以创建连接池。需要连接的每个线程都可以从池中请求一个免费的线程。如果没有可用的连接,则可以通过添加新连接来阻止或扩展池。
有一篇文章here描述了连接池的优缺点(尽管它是基于java的)
编辑:这是关于connection pools in C
的SO问题/答案Edit2:这是一个用C ++编写的示例Connection Pool for MySQL的链接。 (当你实现自己的goto语句时,你应该忽略它。)
答案 2 :(得分:1)
从mySQL文档中可以清楚地看到,任何特定的MYSQL结构都可以毫无困难地在线程中使用 - 同时在不同的线程中使用相同的 MYSQL结构显然会给你带来极不可预测的结果因为状态存储在MYSQL连接中。
因此,要么为每个线程创建一个连接,要么使用上面建议的连接池,并使用某种Mutex保护对该池的访问(即保留或释放连接)。
答案 3 :(得分:-1)
它声明mysql_real_connect()默认情况下不是线程安全的。需要编译客户端库以进行线程访问。