【问题标题】:multi-thread access MySQL error多线程访问MySQL报错
【发布时间】:2009-12-16 13:54:34
【问题描述】:

我编写了一个简单的多线程 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 时,错误仍然存​​在。 那么究竟是什么问题呢?

【问题讨论】:

    标签: mysql c multithreading pthreads


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      当您的生产者和消费者线程休眠时,它们会保持在各自功能期间打开的 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();
      }
      

      简而言之,上述示例应强制在睡眠周期之外建立和关闭连接。我不认为这是最好的代码,但为了您的说明,这应该消除错误。

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

      希望这会有所帮助。

      【讨论】:

      • 嗨,迈克,感谢您的帮助。当我用上面提供的代码替换相应的代码时,创建了四个线程并很快存在,输出只是“hello world”。所以我认为main方法可能有一些错误,真的,我忘了添加join方法,所以我冒着终止main方法的风险,而其他三个线程仍然存在。将 pthread_join() 添加到 main 方法的末尾,不再出现错误。嗯,我是多线程编程新手,你的回复让我想起了join方法,谢谢。
      • 好吧,我试图在我的另一个测试源上使用你的建议,但是一旦它运行 mysql 说“连接太多”,你有比这更好的主意吗?
      猜你喜欢
      • 2010-12-03
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多