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