简体   繁体   English

多线程访问MySQL错误

[英]multi-thread access MySQL error

I have written a simple multi-threaded C program to access MySQL,it works fine except when i add usleep() or sleep() function in each thread function. 我编写了一个简单的多线程C程序来访问MySQL,除了在每个线程函数中添加usleep()或sleep()函数外,它都能正常工作。 i created two pthreads in the main method, 我在main方法中创建了两个pthread,

int main(){
        mysql_library_init(0,NULL,NULL);
        printf("Hello world!\n");
        init_pool(&p,100);
        pthread_t producer;
        pthread_t consumer_1;
        pthread_t consumer_2;
        pthread_create(&producer,NULL,produce_fun,NULL);
        pthread_create(&consumer_1,NULL,consume_fun,NULL);
        pthread_create(&consumer_2,NULL,consume_fun,NULL);
        mysql_library_end();
}



   void * produce_fun(void *arg){
    pthread_detach(pthread_self());
    //procedure
    while(1){
        usleep(500000);
        printf("producer...\n");
        produce(&p,cnt++);
    }
    pthread_exit(NULL);
}

void * consume_fun(void *arg){
    pthread_detach(pthread_self());
    MYSQL db;
    MYSQL *ptr_db=mysql_init(&db);
    mysql_real_connect();

    //procedure
    while(1){
        usleep(1000000);
        printf("consumer...");
        int item=consume(&p);
        addRecord_d(ptr_db,"test",item);
    }
    mysql_thread_end();
    pthread_exit(NULL);
}

void addRecord_d(MYSQL *ptr_db,const char *t_name,int item){
    char query_buffer[100];
    sprintf(query_buffer,"insert into %s values(0,%d)",t_name,item);
//pthread_mutex_lock(&db_t_lock);
    int ret=mysql_query(ptr_db,query_buffer);
    if(ret){
        fprintf(stderr,"%s%s\n","cannot add record to ",t_name);
        return;
    }

    unsigned long long update_id=mysql_insert_id(ptr_db);
//    pthread_mutex_unlock(&db_t_lock);
    printf("add record (%llu,%d) ok.",update_id,item);
}

the program output errors like: 程序输出错误,例如:

[Thread debugging using libthread_db enabled]
[New Thread 0xb7ae3b70 (LWP 7712)]
Hello world!
[New Thread 0xb72d6b70 (LWP 7713)]
[New Thread 0xb6ad5b70 (LWP 7714)]
[New Thread 0xb62d4b70 (LWP 7715)]
[Thread 0xb7ae3b70 (LWP 7712) exited]
producer...
producer...
consumer...consumer...add record (31441,0) ok.add record (31442,1) ok.producer...
producer...
consumer...consumer...add record (31443,2) ok.add record (31444,3) ok.producer...
producer...
consumer...consumer...add record (31445,4) ok.add record (31446,5) ok.producer...
producer...
consumer...consumer...add record (31447,6) ok.add record (31448,7) ok.producer...
Error in my_thread_global_end(): 2 threads didn't exit
[Thread 0xb72d6b70 (LWP 7713) exited]
[Thread 0xb6ad5b70 (LWP 7714) exited]
[Thread 0xb62d4b70 (LWP 7715) exited]

Program exited normally.

and when i add pthread_mutex_lock in function addRecord_d,the error still exists. 当我在函数addRecord_d中添加pthread_mutex_lock时,错误仍然存​​在。 So what exactly the problem is? 那么到底是什么问题呢?

The problem is that you are calling mysql_library_end() too early (especially with the usleep() in the threads). 问题是您调用mysql_library_end()的时间过早(尤其是在线程中使用usleep()时)。 It is possible to finish the main thread and have the other threads continue to do work, but it is not recommended. 可以完成主线程并让其他线程继续工作,但是不建议这样做。 Your solution to add the pthread_join() is the best. 您添加pthread_join()的解决方案是最好的。 You could also eliminate the mysql_library_end() and it will work. 您也可以消除mysql_library_end(),它将起作用。

While your producer and consumer threads sleep, they're holding onto the mysql connections which are open for the duration of the respective functions. 当生产者线程和使用者线程休眠时,它们将保持mysql连接,这些连接在相应功能期间保持打开状态。

When the program tries to end, chances are those threads are sleeping and can not receive the termination signal. 当程序尝试结束时,这些线程很可能正在休眠并且无法接收终止信号。 Hence the error from my_thread_global_end() . 因此,来自my_thread_global_end()的错误。

I don't have access to a dev environment right now, so I can't try your sample. 我目前无法访问开发环境,因此无法尝试您的示例。 But I think this may get past the error, although it would be a highly inefficient code (sample from consume_fun function): 但是我认为这可能会克服错误,尽管这将是效率很低的代码(来自consume_fun函数的示例):

//procedure
while(1){
    usleep(1000000);

    MYSQL *ptr_db=mysql_init(&db);
    mysql_real_connect();

    printf("consumer...");
    int item=consume(&p);
    addRecord_d(ptr_db,"test",item);

    mysql_thread_end();
}

In a nutshell, the above sample should force the connection to be established and closed outside of the sleep cycle. 简而言之,以上示例应强制在睡眠周期之外建立并关闭连接。 I don't think this is the best code, but for the purposes of your illustration, this should get rid of the errors. 我认为这不是最好的代码,但是出于您的说明目的,这应该消除错误。

Keep in mind: this will force you to open and close connections in a loop, which would be a highly inefficient use of resources in a 'production' type environment, so don't do it in real life. 请记住:这将迫使您以循环方式打开和关闭连接,这在“生产”类型的环境中资源的使用效率极低,因此请不要在现实生活中这么做。 :) :)

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM