Mysql C API:如何为每个线程获得一个连接

时间:2017-02-16 12:50:28

标签: mysql c multithreading threadpool mysql-connector

我的程序是一个线程化的Mysql C客户端(用lmysqlclient_r编译,并从main调用mysql_library_init()),它包括在一些Mysql数据库中搜索一些域名。

struct:

的数组names中的域名(t_thconf *th变量)
typedef struct       s_thconf
{
    t_conf  *conf;
    char    *ext;
    char    *origin;
    char    *name;
}                    t_thconf;

struct t_conf只包含mysql配置,如host_ip,用户,端口......发送到mysql_real_connect()。

我使用此Thread pool处理域名,其中每次调用db_domains_query都是一个作业,并按如下方式推送到作业队列中:

  ...
    printf("Making threadpool with %d threads\n", 100);
    threadpool thpool = thpool_init(100);

    while (i < (int)nb_domains)
    {
      printf("%d %s\n", i, th[i].name);
      thpool_add_work(*thpool, (void *)db_domains_query, (void *)&th[i]);
      while ((thpool_jobqueue_length(*thpool) > QUEUE_UNIT))
      usleep(200);
      i += 1;
    }
  ...

// Process one domain name, check if it's existing and update it
void db_domains_query(void *arg)
  {           
    thconf *th = (t_thconf *) arg;
    char query[500];
    char buff[500];
    MYSQL *con = mysql_init(NULL);
    if (!con)
      {
        fprintf(stderr, "mysql_init() failed\n");
        finish_with_error(con);
      }

    if (mysql_real_connect(con, th->conf->server_ip, th->conf->user, th->conf->password, th->conf->database, (unsigned int)th->conf->port, NULL, 0) == NULL)
      finish_with_error(con);

    mysql_set_character_set(con, "utf8");

    mysql_real_escape_string(con, buff, th->name, strlen(th->name));
    sprintf(query, "SELECT Id, DomainName FROM domains where DomainName LIKE '%s';", buff);
    // printf("Thread #%u working on the query = %s\n" (int)pthread_self(), query);

    if (mysql_query(con, query))
      finish_with_error(con);

    MYSQL_RES *result = mysql_store_result(con);
    if (result == NULL)
      finish_with_error(con);

    MYSQL_ROW row;
    if ((row = mysql_fetch_row(result))) 
      {
        printf("Domain name is found : %s %s \n", row[0], row[1]);
      }
    ...
    mysql_thread_end();
    mysql_free_result(result);
    mysql_close(con);
    return ();
 }

如果要处理的域名数量非常合理(最多500,000),这部分代码效果很好。但是,如果我必须处理大量数据(例如&gt; 2,092,900 names,则Mysql服务器似乎要求太多。 它拒绝我的客户,我收到错误&#34; #1040 - 连接太多&#34;,然后&#34;无法在&#39; ip&#39;&#34;上连接到MySQL服务器。 usleep(200)只会延迟错误。

我的猜测是:

  • 一方面,mysql max_connections等于101(我无法更改其值)
  • 另一方面,我声明并向mysql_init()分配一个新的MYSQL *连接到db_domains_query,可能与names一样多。

所以,我的问题是如何重用相同的连接,考虑到1个连接将等于1个线程?我如何调整我的代码以限制连接?

提前致谢。

0 个答案:

没有答案