多线程访问MySQL错误

时间:2009-12-16 13:54:35

标签: mysql c multithreading pthreads

我编写了一个简单的多线程C程序来访问MySQL,除了时,它工作正常 我在每个线程函数中添加了usleep()或sleep()函数。 我在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);
}

程序输出错误如:

[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.

当我在函数addRecord_d中添加pthread_mutex_lock时,错误仍然存​​在。 那究竟是什么问题呢?

2 个答案:

答案 0 :(得分:1)

问题是你太早调用mysql_library_end()(特别是在线程中使用了usleep())。可以完成主线程并让其他线程继续工作,但不建议这样做。您添加pthread_join()的解决方案是最好的。你也可以消除mysql_library_end(),它会起作用。

答案 1 :(得分:0)

当你的生产者和消费者线程睡眠时,他们会抓住在相应功能期间打开的mysql连接。

当程序试图结束时,那些线程可能正在休眠并且无法接收终止信号。因此来自my_thread_global_end()的错误。

我现在无法访问开发环境,因此无法尝试您的示例。但我认为这可能会超过错误,虽然这将是一个非常低效的代码(来自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();
}

简而言之,上述样本应强制建立连接并在睡眠周期之外关闭。我不认为这是最好的代码,但出于说明的目的,这应该摆脱错误。

请记住:这会强制您在循环中打开和关闭连接,这在“生产”类型环境中使用资源非常低效,所以不要在现实生活中这样做。 :)

希望这有帮助。