mysql_init()线程安全问题
2012-11-12 10:28
190 查看
写了个C++的多线程压力测试工具,写了个压测mysql的例子,调用mysql就使用myqsl的c api,
调用mysql的业务代码如下:(都是在线程内部)
先调用一次init()
然后循环调用mysql_execute(),主线程来控制退出时间
最后执行完的时候,再调用一次del()函数
实际执行的时候,在虚拟机上执行1000个并发都没有问题,但是一旦将bin文件拷贝到物理机上执行,在10个线程以下,怎么执行都不会出错,但是线程数大于20个的时候,就会有很大的概率出现sigmentfault
仔细看了下代码实在是看不出哪里有问题,因为本地虚拟机1000个线程跑了20多次,一次都没出现问题. 没办法,只好用coredump来看下问题
查看堆栈
(gdb) where
#0 0x00007fce34f54bf9 in ?? () from /usr/lib64/libmysqlclient.so.16
#1 0x00007fce34f54f23 in ?? () from /usr/lib64/libmysqlclient.so.16
#2 0x00007fce34f5512f in get_charset_by_csname () from /usr/lib64/libmysqlclient.so.16
#3 0x00007fce34f7836a in mysql_init_character_set () from /usr/lib64/libmysqlclient.so.16
#4 0x00007fce34f79b9e in mysql_real_connect () from /usr/lib64/libmysqlclient.so.16
#5 0x0000000000405109 in MultiThread::init (this=0x7fce2800ed30) at run.cpp:130
#6 0x0000000000406af5 in MultiThread::run (this=0x7fce2800ed30) at run.cpp:55
#7 0x0000000000403cef in Thread::run1 (this=0x7fce2800ed30) at ../../include/Thread.h:61
#8 0x0000000000403d2d in Thread::run0 (pVoid=0x7fce2800ed30) at ../../include/Thread.h:45
#9 0x000000304ce064a7 in start_thread () from /lib64/libpthread.so.0
#10 0x000000304c6d3c2d in clone () from /lib64/libc.so.6
可以看到,是在mysql_real_connect() 的时候出错了,最后一个调用函数是get_charset_by_csname () ,也没有其他的信息,可以确定不是自己代码的问题
所以怀疑mysql 的cpi在连接阶段是存在线程不安全的
最后查出来是mysql_init(NULL); 是线程不安全的,在本地线程的相关数据的初始化的时候,会出现问题
简单的解决办法:
在mysql_real_connect()阶段加锁,因为这个是每个线程初始化的时候,只做一次的操作,因此也不会有什么性能损耗,添加了红色代码,再次测试就没有什么问题了
调用mysql的业务代码如下:(都是在线程内部)
void init(){ //pthread_mutex_lock(&work_mutex); my_connection=mysql_init(NULL); if(mysql_real_connect(my_connection,"10.1.147.9","wangzytest","a1234561","wangzy",8066,NULL,0)){ printf("connection successfule \n"); }else{ fprintf(stderr,"connection failed\n"); if(mysql_errno(my_connection)){ fprintf(stderr,"%d,%sn",mysql_errno(my_connection),mysql_error(my_connection)); exit(0); } } //pthread_mutex_unlock(&work_mutex); } int mysql_execute(Result *rs){ if(mysql_query(my_connection,"select * from users")){ rs->result=false; rs->msg = string(mysql_error(my_connection)); return 0; }else{ //suppose in the perf test ,wo don't case the mysql query value only care if the query is successfule; //so here i just free the query result mysql_result = mysql_store_result(my_connection); rs->result=true; rs->msg="ok"; mysql_free_result(mysql_result); return 1; } } void del(){ mysql_close(my_connection); }
先调用一次init()
然后循环调用mysql_execute(),主线程来控制退出时间
最后执行完的时候,再调用一次del()函数
实际执行的时候,在虚拟机上执行1000个并发都没有问题,但是一旦将bin文件拷贝到物理机上执行,在10个线程以下,怎么执行都不会出错,但是线程数大于20个的时候,就会有很大的概率出现sigmentfault
仔细看了下代码实在是看不出哪里有问题,因为本地虚拟机1000个线程跑了20多次,一次都没出现问题. 没办法,只好用coredump来看下问题
查看堆栈
(gdb) where
#0 0x00007fce34f54bf9 in ?? () from /usr/lib64/libmysqlclient.so.16
#1 0x00007fce34f54f23 in ?? () from /usr/lib64/libmysqlclient.so.16
#2 0x00007fce34f5512f in get_charset_by_csname () from /usr/lib64/libmysqlclient.so.16
#3 0x00007fce34f7836a in mysql_init_character_set () from /usr/lib64/libmysqlclient.so.16
#4 0x00007fce34f79b9e in mysql_real_connect () from /usr/lib64/libmysqlclient.so.16
#5 0x0000000000405109 in MultiThread::init (this=0x7fce2800ed30) at run.cpp:130
#6 0x0000000000406af5 in MultiThread::run (this=0x7fce2800ed30) at run.cpp:55
#7 0x0000000000403cef in Thread::run1 (this=0x7fce2800ed30) at ../../include/Thread.h:61
#8 0x0000000000403d2d in Thread::run0 (pVoid=0x7fce2800ed30) at ../../include/Thread.h:45
#9 0x000000304ce064a7 in start_thread () from /lib64/libpthread.so.0
#10 0x000000304c6d3c2d in clone () from /lib64/libc.so.6
可以看到,是在mysql_real_connect() 的时候出错了,最后一个调用函数是get_charset_by_csname () ,也没有其他的信息,可以确定不是自己代码的问题
所以怀疑mysql 的cpi在连接阶段是存在线程不安全的
最后查出来是mysql_init(NULL); 是线程不安全的,在本地线程的相关数据的初始化的时候,会出现问题
简单的解决办法:
在mysql_real_connect()阶段加锁,因为这个是每个线程初始化的时候,只做一次的操作,因此也不会有什么性能损耗,添加了红色代码,再次测试就没有什么问题了
相关文章推荐
- Linux下C/C++连接MySQL之线程安全问题
- Linux/Unix编程中的线程安全问题
- HttpSession的线程安全问题及注意事项
- hibernate中session的线程安全问题
- 创建线程的两种方式区别,安全问题
- Struts的线程安全问题
- mysql线程问题
- 线程安全问题总结
- 线程安全问题————(静态)同步函数
- Servlet线程安全相关问题
- 从volatile说到i++的线程安全问题
- java线程的同步安全问题三种解决办法
- java线程安全之死锁问题
- mysql与redis安全问题
- 关于NSDateFormatter的线程安全问题
- Struts Action的线程安全问题
- java---懒汉式的线程安全问题
- java线程安全问题之静态变量、实例变量、局部变量
- java集合中的线程安全问题
- Java线程安全问题与同步锁